diff --git a/CLI.md b/CLI.md index b9d864705f6b7164e117a588cee922922ca3fc17..c7c5a8dff80a2b743a70af340c1f4d5c8ca91d30 100644 --- a/CLI.md +++ b/CLI.md @@ -11,10 +11,6 @@ [--registry|-r]=[value] [--source|-s]=[value] ``` -# DESCRIPTION - -Template automation - **Usage**: ``` @@ -39,14 +35,6 @@ ## env Show tmpl environment variables - -### set, add - -Set a tmpl environment variable (stored plaintext) - -### unset, delete - -Unsets a tmpl environment variable ## init diff --git a/DOCS.md b/DOCS.md new file mode 100644 index 0000000000000000000000000000000000000000..005df0b563724c88cc5d4cdd6157eeef2b059cf6 --- /dev/null +++ b/DOCS.md @@ -0,0 +1,131 @@ +# tmpl templates + +This documentation aims to cover FAQs and setup. + +## Setting up a template + +A "valid" tmpl template only requires two things + +1. A `template.toml` file in the root directory. +2. A `template` directory that serves as the "root" of the template. + +## template.toml + +**NOTE:** The template.toml file will be expanded, though not with the full power of the template itself. +The template.toml file will only expand environment variables with syntax `$USER` or `${USER}`. +For full documentation on the syntax, see [os.ExpandEnv](https://golang.org/pkg/os/#ExpandEnv). + +When using the `--defaults` flag, no prompts will be shown and only default values will be used. +As another alternative, any environment variable that matches a key will bypass the prompt. +For example, `author` would have the corresponding environment variable `TMPL_VAR_AUTHOR`. + +```toml +# Key-value pairs can be simple +# The user will receive a basic prompt asking them to fill out the variable +project = "my-project" + +# 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 +prompt = "The name of the author of this project" +# 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 +default = "$USER" +``` + +## template directory + +This directory contains any and all files that are part of the template. + +Everything in this directory (including paths and file names!) will be executed as a [Go template](https://golang.org/pkg/text/template/). + +See the [documentation](https://golang.org/pkg/text/template/) for every available possibility, but some basic examples are... + +* A variable defined in template.toml (tmpl allows for keys to be called as a func or variable, whichever you prefer!) + * `{{project}}` or `{{.project}}` + * `{{author}}` or `{{.author}}` +* Conditionally including something + * `{{if eq project ""}} something... {{end}}` + +### template helpers + +For a full list, see [helper.go](registry/helper.go) + +|Helper|Example|Output| +|-----|-----|-----| +|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| +|sep|`{{sep}}`|Filepath separator for current OS| +|time}|`{{time "01/02/2006"}}`|`11/21/2020` - The time according to the given [format](https://flaviocopes.com/go-date-time-format/)| + +## Sources + +tmpl was designed to work with any local or git-based template. Unfortunately, in contrast to boilr, this means +it cannot be used with `user/repo` notation out of the box. + +However, you _can_ set up a source (and subsequent env variable) to make it easier to use your preferred source while +still allowing for others. + +### Setting up a source + +Let's set up a source for [Gitea](https://gitea.com) + +``` +tmpl source add https://gitea.com gitea +``` + +To use it, either pass it in with the `--source` flag + +``` +tmpl --source gitea download jolheiser/tmpls tmpls +``` + +Or set it as the env variable `TMPL_SOURCE` + +## Using a different branch + +By default, tmpl will want to use a branch called `main` in your repository. + +If you are using another branch as your default, you can set it as the env variable `TMPL_BRANCH` + +Alternatively, you can specify on the command-line with the `--branch` flag of the `download` command + +``` +tmpl --source gitea download --branch license jolheiser/tmpls license +``` +The above command would download the [license](https://git.jojodev.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 + 1. `tmpl source add https://github.com github` + 2. Set the env variable `TMPL_SOURCE` to `github` +2. Set the env variable `TMPL_BRANCH` to `master` +3. Happy templating! `tmpl download user/repo repo` + +## Backup and Restore + +1. The simplest solution is to make a copy of your `registry.toml` (default: `~/.tmpl/registry.toml`). + * Once in the new location, you will need to use `tmpl restore`. + +2. Alternatively, you can copy/paste the entire registry (default: `~/.tmpl`) and skip the restore step. + +## `.tmplkeep` + +Perhaps you are familiar with `.gitkeep` and its unofficial status in git. Git does not like empty directories, so usually +a `.gitkeep` (or just `.keep`) file is added to retain the directory while keeping it effectively empty. + +tmpl instead uses `.tmplkeep` files for this purpose. The difference is, tmpl will **not** create the `.tmplkeep` file +when the template is executed. This allows you to set up directory structures (for staging, examples, etc.) that +will *actually* be empty after execution. \ No newline at end of file diff --git a/FAQ.md b/FAQ.md deleted file mode 100644 index b6d813afde7e837d7febfbc90438b0470a39282b..0000000000000000000000000000000000000000 --- a/FAQ.md +++ /dev/null @@ -1,127 +0,0 @@ -# tmpl templates - -This documentation aims to cover FAQs and setup. - -## Setting up a template - -A "valid" tmpl template only requires two things - -1. A `tmpl.yaml` file in the root directory. -2. A `template` directory that serves as the "root" of the template. - -## tmpl.yaml - -**NOTE:** The tmpl.yaml file will be expanded, though not with the full power of the template itself. -The tmpl.yaml file will only expand environment variables with syntax `$USER` or `${USER}`. -For full documentation on the syntax, see [os.ExpandEnv](https://golang.org/pkg/os/#ExpandEnv). - -When using the `--defaults` flag, no prompts will be shown and only default values will be used. -As another alternative, any environment variable that matches a key will bypass the prompt. -For example, `author` would have the corresponding environment variable `TMPL_VAR_AUTHOR`. - -```yaml -# tmpl.yaml -# Write any template args here to prompt the user for, giving any defaults/options as applicable - -prompts: - - id: project # The unique ID for the prompt - label: Project Name # The prompt message/label - help: The name to use in the project # Optional help message for the prompt - default: tmpl # Prompt default -``` - -## template directory - -This directory contains any and all files that are part of the template. - -Everything in this directory (including paths and file names!) will be executed as a [Go template](https://golang.org/pkg/text/template/). - -See the [documentation](https://golang.org/pkg/text/template/) for every available possibility, but some basic examples are... - -* An id defined in `tmpl.yaml` (tmpl allows for keys to be called as a func or variable, whichever you prefer!) - * `{{project}}` or `{{.project}}` - * `{{author}}` or `{{.author}}` -* Conditionally including something - * `{{if eq project ""}} something... {{end}}` - -### template helpers - -For a full list, see [helper.go](registry/helper.go) - -| Helper | Example | Output | -|-------------|----------------------------------|-------------------------------------------------------------------------------------------------------| -| 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 | -| sep | `{{sep}}` | Filepath separator for current OS | -| time | `{{time "01/02/2006"}}` | `11/21/2020` - The time according to the given [format](https://flaviocopes.com/go-date-time-format/) | -| trim_prefix | `{{trim_prefix "foobar" "foo"}}` | `bar` | -| trim_suffix | `{{trim_suffix "foobar" "bar"}}` | `foo` | - -## Sources - -tmpl was designed to work with any local or git-based template. Unfortunately, in contrast to boilr, this means -it cannot be used with `user/repo` notation out of the box. - -However, you _can_ set up a source (and subsequent env variable) to make it easier to use your preferred source while -still allowing for others. - -### Setting up a source - -Let's set up a source for [Gitea](https://gitea.com) - -``` -tmpl source add https://gitea.com gitea -``` - -To use it, either pass it in with the `--source` flag - -``` -tmpl --source gitea download jolheiser/tmpls tmpls -``` - -Or set it as the env variable `TMPL_SOURCE` - -## Using a different branch - -By default, tmpl will want to use a branch called `main` in your repository. - -If you are using another branch as your default, you can set it as the env variable `TMPL_BRANCH` - -Alternatively, you can specify on the command-line with the `--branch` flag of the `download` command - -``` -tmpl --source gitea download --branch license jolheiser/tmpls license -``` -The above command would download the [license](https://git.jojodev.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 - 1. `tmpl source add https://github.com github` - 2. Set the env variable `TMPL_SOURCE` to `github` -2. Set the env variable `TMPL_BRANCH` to `master` -3. Happy templating! `tmpl download user/repo repo` - -## Backup and Restore - -1. The simplest solution is to make a copy of your `registry.toml` (default: `~/.tmpl/registry.toml`). - * Once in the new location, you will need to use `tmpl restore`. - -2. Alternatively, you can copy/paste the entire registry (default: `~/.tmpl`) and skip the restore step. - -## `.tmplkeep` - -Perhaps you are familiar with `.gitkeep` and its unofficial status in git. Git does not like empty directories, so usually -a `.gitkeep` (or just `.keep`) file is added to retain the directory while keeping it effectively empty. - -tmpl instead uses `.tmplkeep` files for this purpose. The difference is, tmpl will **not** create the `.tmplkeep` file -when the template is executed. This allows you to set up directory structures (for staging, examples, etc.) that -will *actually* be empty after execution. \ No newline at end of file diff --git a/README.md b/README.md index 70e91f82201dccdd553b45715ef5965c71959076..c41731578629b89b465b05f4d313687028121a12 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ The two projects share many similarities, however other than general layout/structure the implementation is entirely my own. [CLI Docs](CLI.md) -[Project Docs/FAQs](FAQ.md) +[Project Docs/FAQs](DOCS.md) ## Examples diff --git a/cli.go b/docs.go rename from cli.go rename to docs.go index d7d598801e84a27d4ff05b6db88ff139fe6d429c..00deb1fa59f2a2883ecdb97fa51185fc7f1c512c 100644 --- a/cli.go +++ b/docs.go @@ -11,7 +11,7 @@ "go.jolheiser.com/tmpl/cmd" ) -//go:generate go run cli.go +//go:generate go run docs.go func main() { app := cmd.NewApp() diff --git a/cmd/app.go b/cmd/app.go index a5a9d9c769492e405d18fcc3d5aadcc2b94a3152..1befa0cbcea8e5b05f82a7a775cfc8558fc865af 100644 --- a/cmd/app.go +++ b/cmd/app.go @@ -4,6 +4,8 @@ import ( "os" "path/filepath" + "go.jolheiser.com/tmpl/cmd/flags" + "github.com/rs/zerolog/log" "github.com/urfave/cli/v2" ) @@ -11,16 +13,12 @@ var ( Version = "develop" defaultDir string - - registryFlag string - sourceFlag string ) func init() { home, err := os.UserHomeDir() if err != nil { log.Error().Msg("could not locate user's home directory, tmpl will use temp dir for registry") - defaultDir = filepath.Join(os.TempDir(), ".tmpl") return } defaultDir = filepath.Join(home, ".tmpl") @@ -39,14 +37,14 @@ Aliases: []string{"r"}, Usage: "Registry directory of tmpl", Value: defaultDir, DefaultText: "~/.tmpl", - Destination: ®istryFlag, + Destination: &flags.Registry, EnvVars: []string{"TMPL_REGISTRY"}, }, &cli.StringFlag{ Name: "source", Aliases: []string{"s"}, Usage: "Short-name source to use", - Destination: &sourceFlag, + Destination: &flags.Source, EnvVars: []string{"TMPL_SOURCE"}, }, } diff --git a/cmd/download.go b/cmd/download.go index 90469dd9fb0fc9569ddd1ee10df2302810a6faa3..dac63bb158bcdff5d9545b71f626bef15fa867a1 100644 --- a/cmd/download.go +++ b/cmd/download.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "go.jolheiser.com/tmpl/cmd/flags" "go.jolheiser.com/tmpl/registry" "github.com/rs/zerolog/log" @@ -32,21 +33,21 @@ if ctx.NArg() < 2 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } - reg, err := registry.Open(registryFlag) + reg, err := registry.Open(flags.Registry) if err != nil { return err } var source *registry.Source - if sourceFlag != "" { + if flags.Source != "" { for _, s := range reg.Sources { - if strings.EqualFold(s.Name, sourceFlag) { + if strings.EqualFold(s.Name, flags.Source) { source = s break } } if source == nil { - return fmt.Errorf("could not find source for %s", sourceFlag) + return fmt.Errorf("could not find source for %s", flags.Source) } } diff --git a/cmd/env.go b/cmd/env.go index de252d23460217043be455e963b8777aa7a762a1..703efbf63b1920ca7ccb692c3935bfbc507570ba 100644 --- a/cmd/env.go +++ b/cmd/env.go @@ -3,8 +3,6 @@ import ( "os" - "go.jolheiser.com/tmpl/env" - "github.com/rs/zerolog/log" "github.com/urfave/cli/v2" ) @@ -14,79 +12,20 @@ Name: "env", Usage: "Show tmpl environment variables", Description: "Show tmpl environment variables and their configuration", Action: runEnv, - Subcommands: []*cli.Command{ - { - Name: "set", - Aliases: []string{"add"}, - Usage: "Set a tmpl environment variable (stored plaintext)", - Description: "Set an environment variable that will be loaded specifically when running tmpl (stored plaintext)", - ArgsUsage: "[key] [value]", - Action: runEnvSet, - }, - { - Name: "unset", - Aliases: []string{"delete"}, - Usage: "Unsets a tmpl environment variable", - Description: "Unsets an environment variable previously set for tmpl", - ArgsUsage: "[key]", - Action: runEnvUnset, - }, - }, } func runEnv(_ *cli.Context) error { + // Source - log.Info().Str("TMPL_SOURCE", os.Getenv("TMPL_SOURCE")).Msg("system") + log.Info().Str("TMPL_SOURCE", os.Getenv("TMPL_SOURCE")).Msg("") // Registry Path - log.Info().Str("TMPL_REGISTRY", os.Getenv("TMPL_REGISTRY")).Msg("system") + log.Info().Str("TMPL_REGISTRY", os.Getenv("TMPL_REGISTRY")).Msg("") // Branch - log.Info().Str("TMPL_BRANCH", os.Getenv("TMPL_BRANCH")).Msg("system") - - // Custom - e, err := env.Load(registryFlag) - if err != nil { - return err - } - for key, val := range e { - log.Info().Str(key, val).Msg("env.json") - } + log.Info().Str("TMPL_BRANCH", os.Getenv("TMPL_BRANCH")).Msg("") return nil } -func runEnvSet(ctx *cli.Context) error { - if ctx.NArg() < 2 { - return cli.ShowCommandHelp(ctx, ctx.Command.Name) - } - e, err := env.Load(registryFlag) - if err != nil { - return err - } - key, val := ctx.Args().Get(0), ctx.Args().Get(1) - e[key] = val - if err := env.Save(registryFlag, e); err != nil { - return err - } - log.Info().Str(key, val).Msg("Successfully saved tmpl environment variable!") - return nil -} -func runEnvUnset(ctx *cli.Context) error { - if ctx.NArg() < 1 { - return cli.ShowCommandHelp(ctx, ctx.Command.Name) - } - e, err := env.Load(registryFlag) - if err != nil { - return err - } - key := ctx.Args().First() - val := e[key] - delete(e, key) - if err := env.Save(registryFlag, e); err != nil { - return err - } - log.Info().Str(key, val).Msg("Successfully unset tmpl environment variable!") - return nil -} diff --git a/cmd/flags/flags.go b/cmd/flags/flags.go new file mode 100644 index 0000000000000000000000000000000000000000..8bc7cac7eb466a22fda15b2a76f075f6fed2fb17 --- /dev/null +++ b/cmd/flags/flags.go @@ -0,0 +1,6 @@ +package flags + +var ( + Registry string + Source string +) diff --git a/cmd/init.go b/cmd/init.go index 61c916c5ecfed7e0cb3716dae628cff5e8f93a62..08ba88c7ae296de73659fa81cba2a498725de5c1 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -16,11 +16,11 @@ Action: runInit, } func runInit(_ *cli.Context) error { - if _, err := os.Lstat("tmpl.yaml"); !os.IsNotExist(err) { + if _, err := os.Lstat("template.toml"); !os.IsNotExist(err) { if err != nil { return err } - return errors.New("tmpl.yaml already detected, aborting initialization") + return errors.New("template.toml already detected, aborting initialization") } if fi, err := os.Lstat("template"); !os.IsNotExist(err) { if err != nil { @@ -32,7 +32,7 @@ } return errors.New("template directory already detected, aborting initialization") } - fi, err := os.Create("tmpl.yaml") + fi, err := os.Create("template.toml") if err != nil { return err } @@ -46,12 +46,11 @@ log.Info().Msg("Template initialized!") return fi.Close() } -var comments = `# tmpl.yaml +var comments = `# template.toml # Write any template args here to prompt the user for, giving any defaults/options as applicable -prompts: - - id: name # The unique ID for the prompt - label: Project Name # The prompt message/label - help: The name to use in the project # Optional help message for the prompt - default: tmpl # Prompt default +[name] +prompt = "Project Name" +help = "The name to use in the project" +default = "tmpl" ` diff --git a/cmd/list.go b/cmd/list.go index 32002bef12ef1fed10fd1aab583bc62557307709..4f7143d018b960402d3ec232b9f94da9cf0a9c36 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -5,6 +5,7 @@ "fmt" "os" "text/tabwriter" + "go.jolheiser.com/tmpl/cmd/flags" "go.jolheiser.com/tmpl/registry" "github.com/urfave/cli/v2" @@ -18,7 +19,7 @@ Action: runList, } func runList(_ *cli.Context) error { - reg, err := registry.Open(registryFlag) + reg, err := registry.Open(flags.Registry) if err != nil { return err } diff --git a/cmd/remove.go b/cmd/remove.go index c424517bcf844ca9e0dcdf68b92f4f55e5939fb4..98001187a55600aca14c128a72e774960bd0af18 100644 --- a/cmd/remove.go +++ b/cmd/remove.go @@ -1,6 +1,7 @@ package cmd import ( + "go.jolheiser.com/tmpl/cmd/flags" "go.jolheiser.com/tmpl/registry" "github.com/rs/zerolog/log" @@ -20,7 +21,7 @@ if ctx.NArg() < 1 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } - reg, err := registry.Open(registryFlag) + reg, err := registry.Open(flags.Registry) if err != nil { return err } diff --git a/cmd/restore.go b/cmd/restore.go index c88dc25aa5c5b2636d7f95b11046f85dc1a69319..cf96172f2d8f833eaeaa618b916c13383ab2a5a6 100644 --- a/cmd/restore.go +++ b/cmd/restore.go @@ -3,6 +3,7 @@ import ( "os" + "go.jolheiser.com/tmpl/cmd/flags" "go.jolheiser.com/tmpl/registry" "github.com/rs/zerolog/log" @@ -17,7 +18,7 @@ Action: runRestore, } func runRestore(_ *cli.Context) error { - reg, err := registry.Open(registryFlag) + reg, err := registry.Open(flags.Registry) if err != nil { return err } diff --git a/cmd/save.go b/cmd/save.go index 508f683abe050e43358c2e62c0fa77cf08202879..8b8ccfc5c9f762fc82cc8f45f66e5ced748fe5b6 100644 --- a/cmd/save.go +++ b/cmd/save.go @@ -3,6 +3,7 @@ import ( "path/filepath" + "go.jolheiser.com/tmpl/cmd/flags" "go.jolheiser.com/tmpl/registry" "github.com/rs/zerolog/log" @@ -22,7 +23,7 @@ if ctx.NArg() < 2 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } - reg, err := registry.Open(registryFlag) + reg, err := registry.Open(flags.Registry) if err != nil { return err } diff --git a/cmd/source.go b/cmd/source.go index 1a5f820279092622d0ae16f29eb41e8269d1ce3a..355038edaedb86efc868c91bd99ffce02fe67824 100644 --- a/cmd/source.go +++ b/cmd/source.go @@ -5,6 +5,7 @@ "fmt" "os" "text/tabwriter" + "go.jolheiser.com/tmpl/cmd/flags" "go.jolheiser.com/tmpl/registry" "github.com/rs/zerolog/log" @@ -49,7 +50,7 @@ } ) func runSourceList(_ *cli.Context) error { - reg, err := registry.Open(registryFlag) + reg, err := registry.Open(flags.Registry) if err != nil { return err } @@ -71,7 +72,7 @@ if ctx.NArg() < 2 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } - reg, err := registry.Open(registryFlag) + reg, err := registry.Open(flags.Registry) if err != nil { return err } @@ -90,7 +91,7 @@ if ctx.NArg() < 1 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } - reg, err := registry.Open(registryFlag) + reg, err := registry.Open(flags.Registry) if err != nil { return err } diff --git a/cmd/test.go b/cmd/test.go index 1cb327feccc9469153c26270bd0786960ecb5a56..44502237b7bb70d29c2cb7f798a7bbad6f52e1c7 100644 --- a/cmd/test.go +++ b/cmd/test.go @@ -1,12 +1,8 @@ package cmd import ( - "errors" - "fmt" "os" "path/filepath" - - "go.jolheiser.com/tmpl/schema" "github.com/rs/zerolog/log" "github.com/urfave/cli/v2" @@ -27,28 +23,15 @@ testPath = ctx.Args().First() } var errs []string - - fi, err := os.Open(filepath.Join(testPath, "tmpl.yaml")) - if err != nil { - errs = append(errs, fmt.Sprintf("could not open tmpl.yaml: %v", err)) - } - defer fi.Close() - if err := schema.Lint(fi); err != nil { - var rerr schema.ResultErrors - if errors.As(err, &rerr) { - for _, re := range rerr { - errs = append(errs, fmt.Sprintf("%s: %s", re.Field(), re.Description())) - } - } else { - errs = append(errs, fmt.Sprintf("could not lint tmpl.yaml: %v", err)) - } + if _, err := os.Lstat(filepath.Join(testPath, "template.toml")); err != nil { + errs = append(errs, "could not find template.toml") } - fstat, err := os.Lstat(filepath.Join(testPath, "template")) + fi, err := os.Lstat(filepath.Join(testPath, "template")) if err != nil { errs = append(errs, "no template directory found") } - if err == nil && !fstat.IsDir() { + if err == nil && !fi.IsDir() { errs = append(errs, "template path is a file, not a directory") } @@ -58,7 +41,6 @@ log.Error().Msg(err) } return nil } - - log.Info().Msg("This is a valid tmpl template!") + log.Info().Msg("this is a valid tmpl template") return nil } diff --git a/cmd/update.go b/cmd/update.go index f71efe3190e2ddc3f27d02012ce65867eb66a5ea..d621bc6422fb148c34ad2ff981d1322f3b00e90b 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -1,6 +1,7 @@ package cmd import ( + "go.jolheiser.com/tmpl/cmd/flags" "go.jolheiser.com/tmpl/registry" "github.com/rs/zerolog/log" @@ -20,7 +21,7 @@ if ctx.NArg() < 1 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } - reg, err := registry.Open(registryFlag) + reg, err := registry.Open(flags.Registry) if err != nil { return err } diff --git a/cmd/use.go b/cmd/use.go index dfe03596ac42866074a2b71d08449336a5bbdfad..74fa3d63419e3e3e4f911774246461cf0c41dd17 100644 --- a/cmd/use.go +++ b/cmd/use.go @@ -1,7 +1,7 @@ package cmd import ( - "go.jolheiser.com/tmpl/env" + "go.jolheiser.com/tmpl/cmd/flags" "go.jolheiser.com/tmpl/registry" "github.com/rs/zerolog/log" @@ -36,16 +36,8 @@ if ctx.NArg() >= 2 { dest = ctx.Args().Get(1) } - reg, err := registry.Open(registryFlag) - if err != nil { - return err - } - - e, err := env.Load(registryFlag) + reg, err := registry.Open(flags.Registry) if err != nil { - return err - } - if err := e.Set(); err != nil { return err } diff --git a/config/config.go b/config/config.go deleted file mode 100644 index c3067433cddb69cb037ade4d4a0ede6116f8d7ea..0000000000000000000000000000000000000000 --- a/config/config.go +++ /dev/null @@ -1,41 +0,0 @@ -package config - -import ( - "fmt" - "io" - "os" - "strings" - - "gopkg.in/yaml.v3" -) - -// Config is a tmpl config -type Config struct { - Prompts []Prompt `yaml:"prompts"` -} - -// Prompt is a tmpl prompt -type Prompt struct { - ID string `yaml:"id"` - Label string `yaml:"label"` - Help string `yaml:"help"` - Default any `yaml:"default"` -} - -// Load loads a tmpl config -func Load(r io.Reader) (*Config, error) { - configBytes, err := io.ReadAll(r) - if err != nil { - return nil, err - } - - configContents := os.Expand(string(configBytes), func(s string) string { - if strings.HasPrefix(s, "TMPL_PROMPT") { - return fmt.Sprintf("${%s}", s) - } - return os.Getenv(s) - }) - - var c Config - return &c, yaml.Unmarshal([]byte(configContents), &c) -} diff --git a/env/env.go b/env/env.go deleted file mode 100644 index 6c091ec0bc154db6a7e552394d31622ec8fb6774..0000000000000000000000000000000000000000 --- a/env/env.go +++ /dev/null @@ -1,50 +0,0 @@ -package env - -import ( - "encoding/json" - "errors" - "os" - "path/filepath" -) - -// Env is tmpl environment variables -type Env map[string]string - -// Set sets all environment variables from an Env -func (e Env) Set() error { - for key, val := range e { - if err := os.Setenv(key, val); err != nil { - return err - } - } - return nil -} - -// Load loads an env from /env.json -func Load(path string) (Env, error) { - p := filepath.Join(path, "env.json") - fi, err := os.Open(p) - if err != nil { - if errors.Is(err, os.ErrNotExist) { - return Env{}, nil - } - return nil, err - } - defer fi.Close() - - var e Env - if err := json.NewDecoder(fi).Decode(&e); err != nil { - return nil, err - } - return e, nil -} - -// Save saves an Env to /env.json -func Save(path string, e Env) error { - p := filepath.Join(path, "env.json") - fi, err := os.Create(p) - if err != nil { - return err - } - return json.NewEncoder(fi).Encode(e) -} diff --git a/go.mod b/go.mod index e0e059104ef876ea2f60394458d255f3f99c2697..63613e52265b7222b269d692526d2eb288e9ce40 100644 --- a/go.mod +++ b/go.mod @@ -1,55 +1,15 @@ module go.jolheiser.com/tmpl -go 1.18 +go 1.15 require ( - github.com/AlecAivazis/survey/v2 v2.3.5 - github.com/go-git/go-git/v5 v5.4.2 + github.com/AlecAivazis/survey/v2 v2.2.2 + github.com/go-git/go-git/v5 v5.2.0 github.com/huandu/xstrings v1.3.2 - github.com/matryer/is v1.4.0 - github.com/mholt/archiver/v3 v3.5.1 - github.com/rs/zerolog v1.27.0 - github.com/urfave/cli/v2 v2.8.1 - github.com/xeipuuv/gojsonschema v1.2.0 - gopkg.in/yaml.v3 v3.0.1 -) - -require ( - github.com/Microsoft/go-winio v0.5.2 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20220517143526-88bb52951d5b // indirect - github.com/acomagu/bufpipe v1.0.3 // indirect - github.com/andybalholm/brotli v1.0.4 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/go-git/gcfg v1.5.0 // indirect - github.com/go-git/go-billy/v5 v5.3.1 // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/imdario/mergo v0.3.13 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect - github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/klauspost/compress v1.15.6 // indirect - github.com/klauspost/pgzip v1.2.5 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect - github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/nwaples/rardecode v1.1.3 // indirect - github.com/pierrec/lz4/v4 v4.1.14 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sergi/go-diff v1.2.0 // indirect - github.com/stretchr/testify v1.7.1 // indirect - github.com/ulikunitz/xz v0.5.10 // indirect - github.com/xanzy/ssh-agent v0.3.1 // indirect - github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect - github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect - github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect - golang.org/x/net v0.0.0-20220607020251-c690dde0001d // indirect - golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d // indirect - golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect - golang.org/x/text v0.3.7 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect + github.com/mattn/go-isatty v0.0.12 // indirect + github.com/mholt/archiver/v3 v3.5.0 + github.com/pelletier/go-toml v1.8.1 + github.com/rs/zerolog v1.26.0 + github.com/urfave/cli/v2 v2.3.0 + golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9 // indirect ) diff --git a/go.sum b/go.sum index 5be3a0dc3a3922a52626dad82630f2c5d8246b58..2901739a5e00ee535150e20ed6c4e4a11a11d624 100644 --- a/go.sum +++ b/go.sum @@ -1,202 +1,162 @@ -github.com/AlecAivazis/survey/v2 v2.3.5 h1:A8cYupsAZkjaUmhtTYv3sSqc7LO5mp1XDfqe5E/9wRQ= -github.com/AlecAivazis/survey/v2 v2.3.5/go.mod h1:4AuI9b7RjAR+G7v9+C4YSlX/YL3K3cWNXgWXOhllqvI= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s= -github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= -github.com/ProtonMail/go-crypto v0.0.0-20220517143526-88bb52951d5b h1:lcbBNuQhppsc7A5gjdHmdlqUqJfgGMylBdGyDs0j7G8= -github.com/ProtonMail/go-crypto v0.0.0-20220517143526-88bb52951d5b/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= -github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= -github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= -github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= -github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= -github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/AlecAivazis/survey/v2 v2.2.2 h1:1I4qBrNsHQE+91tQCqVlfrKe9DEL65949d1oKZWVELY= +github.com/AlecAivazis/survey/v2 v2.2.2/go.mod h1:9FJRdMdDm8rnT+zHVbvQT2RTSTLq0Ttd6q3Vl2fahjk= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= +github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= +github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= +github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= +github.com/andybalholm/brotli v1.0.0 h1:7UCwP93aiSfvWpapti8g88vVVGp2qqtGyePsSuDafo4= +github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= -github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY= -github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= +github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= +github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= +github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= -github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= -github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8= -github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= -github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= -github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= +github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM= +github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M= +github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= +github.com/go-git/go-git/v5 v5.2.0 h1:YPBLG/3UK1we1ohRkncLjaXWLW+HKp5QNM/jTli2JgI= +github.com/go-git/go-git/v5 v5.2.0/go.mod h1:kh02eMX+wdqqxgNMEyq8YgwlIOsDOa9homkUq1PoTMs= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog= -github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= +github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= +github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg= +github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= -github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= +github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.15.6 h1:6D9PcO8QWu0JyaQ2zUMmu16T1T+zjjEpP91guRsvDfY= -github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/compress v1.10.10 h1:a/y8CglcM7gLGYmlbP/stPE5sR3hbhFRUjCBfd/0B3I= +github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= -github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/klauspost/pgzip v1.2.4 h1:TQ7CNpYKovDOmqzRHKxJh0BeaBI7UdQZYc6p7pMQh1A= +github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.4 h1:5Myjjh3JY/NaAi4IsUbHADytDyl1VE1Y9PXDlL+P/VQ= +github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= -github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= +github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= -github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= -github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= +github.com/mholt/archiver/v3 v3.5.0 h1:nE8gZIrw66cu4osS/U7UW7YDuGMHssxKutU8IfWxwWE= +github.com/mholt/archiver/v3 v3.5.0/go.mod h1:qqTTPUK/HZPFgFQ/TJ3BzvTpF/dPtFVJXdQbCmeMxwc= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ= github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= -github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc= -github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= -github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE= -github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/pierrec/lz4/v4 v4.0.3 h1:vNQKSVZNYUEAvRY9FaUXAF1XPbSOHJtDTiP41kzDz2E= +github.com/pierrec/lz4/v4 v4.0.3/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs= -github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/rs/zerolog v1.26.0 h1:ORM4ibhEZeTeQlCojCK2kPz1ogAY4bGs4tD+SaAdGaE= +github.com/rs/zerolog v1.26.0/go.mod h1:yBiM87lvSqX8h0Ww4sdzNSkVYZ8dL2xjZJG1lAuGZEo= +github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= -github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= -github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/urfave/cli/v2 v2.8.1 h1:CGuYNZF9IKZY/rfBe3lJpccSoIY1ytfvmgQT90cNOl4= -github.com/urfave/cli/v2 v2.8.1/go.mod h1:Z41J9TPoffeoqP0Iza0YbAhGvymRdZAd2uPmZ5JxRdY= -github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= -github.com/xanzy/ssh-agent v0.3.1 h1:AmzO1SSWxw73zxFZPRwaMN1MohDw8UyHnmuxyceTEGo= -github.com/xanzy/ssh-agent v0.3.1/go.mod h1:QIE4lCeL7nkC25x+yA3LBIYfwCc1TFziCtG7cBAac6w= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/ulikunitz/xz v0.5.7 h1:YvTNdFzX6+W5m9msiYg/zpkSURPPtOlzbqYjrFn7Yt4= +github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= +github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9 h1:umElSU9WZirRdgu2yFHY0ayQkEnKiOC1TtM3fWXFnoU= +golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d h1:Zu/JngovGLVi6t2J3nmAf3AoTDwuzw85YZ3b9o4yU7s= -golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= -golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 h1:CBpWXWQpIRjzmkkA+M7q9Fqnwd2mZr3AFqexg8YTfoM= -golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/registry/error.go b/registry/error.go index 168ed929ef5f93ace3fb96ec123d759ef18afcf5..f7950f4e65e6ce1efca168980d7f4479cfc92c2a 100644 --- a/registry/error.go +++ b/registry/error.go @@ -23,6 +23,11 @@ func (e ErrTemplateNotFound) Error() string { return fmt.Sprintf("template not found for %s", e.Name) } +func IsErrTemplateNotFound(err error) bool { + _, ok := err.(ErrTemplateNotFound) + return ok +} + type ErrSourceNotFound struct { Name string } diff --git a/registry/helper.go b/registry/helper.go index a9bb49d27217bd38b0e6b206d98e7ded4830bb7a..2ce93cb0cc6ec2b8975c8b6b34c8cf6ef05d1eab 100644 --- a/registry/helper.go +++ b/registry/helper.go @@ -9,7 +9,8 @@ "github.com/huandu/xstrings" ) -var funcMap = map[string]any{ +var funcMap = map[string]interface{}{ + // String conversions "upper": strings.ToUpper, "lower": strings.ToLower, @@ -19,12 +20,6 @@ "kebab": xstrings.ToKebabCase, "pascal": xstrings.ToCamelCase, "camel": func(in string) string { return xstrings.FirstRuneToLower(xstrings.ToCamelCase(in)) - }, - "trim_prefix": func(in, trim string) string { - return strings.TrimPrefix(in, trim) - }, - "trim_suffix": func(in, trim string) string { - return strings.TrimSuffix(in, trim) }, // Other diff --git a/registry/prompt.go b/registry/prompt.go index e12adcecb9baf93c4ce71d614afe9f25f9a1d766..d0d34cfa2852248c909e09c5b547608325068458 100644 --- a/registry/prompt.go +++ b/registry/prompt.go @@ -2,97 +2,112 @@ package registry import ( "fmt" + "io/ioutil" "os" "path/filepath" + "sort" "strings" "text/template" - - "go.jolheiser.com/tmpl/config" "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, "tmpl.yaml") - fi, err := os.Open(templatePath) + templatePath := filepath.Join(dir, "template.toml") + if _, err := os.Lstat(templatePath); err != nil { + return nil, err + } + + templateBytes, err := ioutil.ReadFile(templatePath) if err != nil { return nil, err } - defer fi.Close() - cfg, err := config.Load(fi) + // Expand the template with environment variables + templateContents := os.ExpandEnv(string(templateBytes)) + + tree, err := toml.Load(templateContents) if err != nil { return nil, err } - prompts := make(templatePrompts, 0, len(cfg.Prompts)) - for _, prompt := range cfg.Prompts { - tp := templatePrompt{ - Prompt: prompt, + 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 } - if tp.Label == "" { - tp.Label = tp.ID + p.Key = k + if p.Message == "" { + p.Message = p.Key } - if tp.Default == nil { - tp.Default = "" + if p.Default == nil { + p.Default = "" } - prompts = append(prompts, tp) + prompts[idx] = p } + // Sort the prompts so they are consistent + sort.Sort(prompts) + for idx, prompt := range prompts { // Check for env variable - envKey := strings.ToUpper(prompt.ID) - if e, ok := os.LookupEnv(fmt.Sprintf("TMPL_VAR_%s", envKey)); ok { + if e, ok := os.LookupEnv(fmt.Sprintf("TMPL_VAR_%s", strings.ToUpper(prompt.Key))); ok { prompts[idx].Value = e - os.Setenv(fmt.Sprintf("TMPL_PROMPT_%s", envKey), e) continue } // Check if we are using defaults if defaults { - val := prompt.Default - switch t := prompt.Default.(type) { - case []string: - for idy, s := range t { - t[idy] = os.ExpandEnv(s) - } - val = t - case string: - val = os.ExpandEnv(t) - } - s := fmt.Sprint(val) - prompts[idx].Value = s - os.Setenv(fmt.Sprintf("TMPL_PROMPT_%s", envKey), s) + prompts[idx].Value = prompt.Default continue } var p survey.Prompt switch t := prompt.Default.(type) { case []string: - for idy, s := range t { - t[idy] = os.ExpandEnv(s) - } p = &survey.Select{ - Message: prompt.Label, + Message: prompt.Message, Options: t, Help: prompt.Help, } case bool: p = &survey.Confirm{ - Message: prompt.Label, + Message: prompt.Message, Default: t, Help: prompt.Help, } case string: p = &survey.Input{ - Message: prompt.Label, - Default: os.ExpandEnv(t), + Message: prompt.Message, + Default: t, Help: prompt.Help, } default: p = &survey.Input{ - Message: prompt.Label, - Default: fmt.Sprint(t), + Message: prompt.Message, + Default: fmt.Sprintf("%v", t), Help: prompt.Help, } } @@ -101,36 +116,45 @@ if err := survey.AskOne(p, &a); err != nil { return nil, err } prompts[idx].Value = a - os.Setenv(fmt.Sprintf("TMPL_PROMPT_%s", envKey), a) } return prompts, nil } -type templatePrompt struct { - config.Prompt - Value string -} - type templatePrompts []templatePrompt // ToMap converts a slice to templatePrompt into a suitable template context -func (t templatePrompts) ToMap() map[string]any { - m := make(map[string]any) +func (t templatePrompts) ToMap() map[string]interface{} { + m := make(map[string]interface{}) for _, p := range t { - m[p.ID] = p.Value + m[p.Key] = p.Value } return m } // ToFuncMap converts a slice of templatePrompt into a suitable template.FuncMap func (t templatePrompts) ToFuncMap() template.FuncMap { - m := make(map[string]any) + m := make(map[string]interface{}) for k, v := range t.ToMap() { vv := v // Enclosure - m[k] = func() any { + m[k] = func() interface{} { return vv } } return m } + +// Len is for sort.Sort +func (t templatePrompts) Len() int { + return len(t) +} + +// Less is for sort.Sort +func (t templatePrompts) Less(i, j int) bool { + return t[i].Key > t[j].Key +} + +// Swap is for sort.Sort +func (t templatePrompts) Swap(i, j int) { + t[i], t[j] = t[j], t[i] +} diff --git a/registry/registry.go b/registry/registry.go index a0f40aeea8d764ec9d1dce0ee801cdd5b8d40c21..d2ddf01e4d13496e46b74255217518859c46fdff 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -11,14 +11,14 @@ "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/mholt/archiver/v3" - "gopkg.in/yaml.v3" + "github.com/pelletier/go-toml" ) // Registry is a collection of Template type Registry struct { dir string - Sources []*Source `yaml:"sources"` - Templates []*Template `yaml:"templates"` + Sources []*Source `toml:"sources"` + Templates []*Template `toml:"templates"` } func (r *Registry) save() error { @@ -26,7 +26,7 @@ fi, err := os.Create(r.MetaFilePath()) if err != nil { return err } - if err := yaml.NewEncoder(fi).Encode(r); err != nil { + if err := toml.NewEncoder(fi).Encode(r); err != nil { return err } return fi.Close() @@ -34,7 +34,7 @@ } // MetaFilePath is the path to the Registry meta-file func (r *Registry) MetaFilePath() string { - return filepath.Join(r.dir, "registry.yaml") + return filepath.Join(r.dir, "registry.toml") } // GetTemplate retrieves a Template from the Registry @@ -111,7 +111,7 @@ return nil } -// UpdateTemplate updates the Template on disk and in meta +// RemoveTemplate updates the Template on disk and in meta func (r *Registry) UpdateTemplate(name string) error { _, err := r.GetTemplate(name) if err != nil { @@ -195,12 +195,12 @@ return nil, err } } - contents, err := os.ReadFile(reg.MetaFilePath()) + tree, err := toml.LoadFile(reg.MetaFilePath()) if err != nil { return nil, err } - if err := yaml.Unmarshal(contents, ®); err != nil { + if err := tree.Unmarshal(®); err != nil { return nil, err } @@ -254,8 +254,9 @@ return nil } func save(source, dest string) error { + // Make sure it's a valid template - if _, err := os.Lstat(filepath.Join(source, "tmpl.yaml")); err != nil { + if _, err := os.Lstat(filepath.Join(source, "template.toml")); err != nil { return err } fi, err := os.Lstat(filepath.Join(source, "template")) diff --git a/registry/registry_test.go b/registry/registry_test.go index eb99ce1b26218e84c6577d9c91d75ef64e7690fd..628e29dc09b5359e0650526c7661837a9a477384 100644 --- a/registry/registry_test.go +++ b/registry/registry_test.go @@ -1,24 +1,26 @@ package registry import ( - "errors" "fmt" "io/ioutil" "os" "path/filepath" "testing" - - "github.com/matryer/is" ) var ( tmplDir string regDir string + destDir string reg *Registry ) func TestMain(m *testing.M) { var err error + destDir, err = ioutil.TempDir(os.TempDir(), "tmpl-dest") + if err != nil { + panic(err) + } // Set up template setupTemplate() @@ -28,6 +30,9 @@ setupRegistry() status := m.Run() + if err = os.RemoveAll(destDir); err != nil { + fmt.Printf("could not clean up temp directory %s\n", destDir) + } if err = os.RemoveAll(tmplDir); err != nil { fmt.Printf("could not clean up temp directory %s\n", tmplDir) } @@ -46,22 +51,25 @@ t.Run("execute", testExecute) } func testSave(t *testing.T) { - assert := is.New(t) - _, err := reg.SaveTemplate("test", tmplDir) - assert.NoErr(err) // Should save template + if _, err := reg.SaveTemplate("test", tmplDir); err != nil { + t.Log("could not save template") + t.FailNow() + } } func testGet(t *testing.T) { - assert := is.New(t) _, err := reg.GetTemplate("test") - assert.NoErr(err) // Should get template + if err != nil { + t.Logf("could not get template") + t.FailNow() + } } func testGetFail(t *testing.T) { - assert := is.New(t) _, err := reg.GetTemplate("fail") - if !errors.As(err, &ErrTemplateNotFound{}) { - assert.Fail() // Template should not exist + if !IsErrTemplateNotFound(err) { + t.Logf("template should not exist") + t.FailNow() } } @@ -73,7 +81,7 @@ panic(err) } // Template config - fi, err := os.Create(filepath.Join(tmplDir, "tmpl.yaml")) + fi, err := os.Create(filepath.Join(tmplDir, "template.toml")) if err != nil { panic(err) } diff --git a/registry/source.go b/registry/source.go index 7e9029082222a87c205e1a192ab3681d429e973b..7770538f8756aacb8cd0da0b6110351fae86318c 100644 --- a/registry/source.go +++ b/registry/source.go @@ -5,8 +5,8 @@ // Source is a quick way to specify a git source // e.g. Gitea, GitHub, etc. type Source struct { - Name string `yaml:"name"` - URL string `yaml:"url"` + Name string `toml:"name"` + URL string `toml:"url"` } // CloneURL constructs a URL suitable for cloning a repository diff --git a/registry/source_test.go b/registry/source_test.go index 950e068251c0700d826399d7b7544e4891883c27..26134410acc69401a1261858e3fbea271701f95c 100644 --- a/registry/source_test.go +++ b/registry/source_test.go @@ -1,14 +1,11 @@ package registry import ( + "strings" "testing" - - "github.com/matryer/is" ) func TestSource(t *testing.T) { - assert := is.New(t) - tt := []struct { Name string Source *Source @@ -41,7 +38,10 @@ namespace := "user/repo" for _, tc := range tt { t.Run(tc.Name, func(t *testing.T) { cloneURL := tc.Source.CloneURL(namespace) - assert.Equal(tc.CloneURL, cloneURL) // Clone URLs should match + if !strings.EqualFold(tc.CloneURL, cloneURL) { + t.Logf("incorrect clone URL:\n\tExpected: %s\n\tGot: %s\n", tc.CloneURL, cloneURL) + t.Fail() + } }) } } diff --git a/registry/template.go b/registry/template.go index c60e03aebe2f61ccb3f28392d8b5ca555ea56efd..76bf84c425959dc4e15facc9726d9a22ba620ca5 100644 --- a/registry/template.go +++ b/registry/template.go @@ -15,12 +15,12 @@ ) // Template is a tmpl project type Template struct { - reg *Registry `yaml:"-"` - Name string `yaml:"name"` - Path string `yaml:"path"` - Repository string `yaml:"repository"` - Branch string `yaml:"branch"` - LastUpdate time.Time `yaml:"last_update"` + reg *Registry `toml:"-"` + Name string `toml:"name"` + Path string `toml:"path"` + Repository string `toml:"repository"` + Branch string `toml:"branch"` + LastUpdate time.Time `toml:"last_update"` } // ArchiveName is the name given to the archive for this Template @@ -51,6 +51,7 @@ return err } funcs := mergeMaps(funcMap, prompts.ToFuncMap()) + base := filepath.Join(tmp, "template") return filepath.Walk(base, func(walkPath string, walkInfo os.FileInfo, walkErr error) error { if walkErr != nil { @@ -116,8 +117,8 @@ return newFi.Close() }) } -func mergeMaps(maps ...map[string]any) map[string]any { - m := make(map[string]any) +func mergeMaps(maps ...map[string]interface{}) map[string]interface{} { + m := make(map[string]interface{}) for _, mm := range maps { for k, v := range mm { m[k] = v diff --git a/registry/template_test.go b/registry/template_test.go index 138d84d12cf94a9e0eaa75cc77e7bdb0463d1b49..a51717be1396de93d93f661ffb6b77aafad1bf12 100644 --- a/registry/template_test.go +++ b/registry/template_test.go @@ -5,74 +5,99 @@ "io/ioutil" "os" "path/filepath" "testing" - - "github.com/matryer/is" ) var ( - tmplContents = `{{title name}} (@{{username}}) {{if .bool}}{{.year}}{{end}} {{org}}` + tmplContents = `{{title name}} (@{{username}}) {{if .bool}}{{.year}}{{end}}` tmplTemplate = ` -prompts: - - id: name - default: john olheiser - - id: year - default: ${TMPL_TEST} # 2020 - - id: package - default: pkg - - id: bool - default: true - - id: username - default: username - - id: org - default: ${TMPL_PROMPT_USERNAME}/org +name = "john olheiser" + +[year] +default = ${TMPL_TEST} # 2020 + +[package] +default = "pkg" + +[bool] +default = true + +[username] +default = "username" ` - tmplGold = "John Olheiser (@jolheiser) 2020 jolheiser/org" + tmplGold = "John Olheiser (@jolheiser) 2020" tmplNewGold = "DO NOT OVERWRITE!" ) func testExecute(t *testing.T) { - assert := is.New(t) - destDir := t.TempDir() - // Set environment variable - err := os.Setenv("TMPL_TEST", "2020") - assert.NoErr(err) // Should set TMPL_TEST env - - err = os.Setenv("TMPL_VAR_USERNAME", "jolheiser") - assert.NoErr(err) // Should set TMPL_VAR_USERNAME env + if err := os.Setenv("TMPL_TEST", "2020"); err != nil { + t.Logf("could not set environment: %v", err) + t.FailNow() + } + if err := os.Setenv("TMPL_VAR_USERNAME", "jolheiser"); err != nil { + t.Logf("could not set environment: %v", err) + t.FailNow() + } // Get template tmpl, err := reg.GetTemplate("test") - assert.NoErr(err) // Should get template + if err != nil { + t.Logf("could not get template") + t.FailNow() + } // Execute template - err = tmpl.Execute(destDir, true, true) - assert.NoErr(err) // Should 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) - assert.NoErr(err) // Should be able to read TEST file - assert.Equal(string(contents), tmplGold) // Template should match golden file + 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") - _, err = os.Lstat(pkgPath) - assert.NoErr(err) // PKG directory should exist + if _, err := os.Lstat(pkgPath); err != nil { + t.Logf("expected a directory at %s: %v\n", pkgPath, err) + t.FailNow() + } // Check for .tmplkeep tmplKeep := filepath.Join(pkgPath, ".tmplkeep") - _, err = os.Lstat(tmplKeep) - assert.True(err != nil) // .tmplkeep file should NOT be retained + if _, err := os.Lstat(tmplKeep); err == nil { + t.Logf(".tmplkeep files should NOT be retained upon execution: %s\n", tmplKeep) + t.FailNow() + } // Change file to test non-overwrite - err = ioutil.WriteFile(testPath, []byte(tmplNewGold), os.ModePerm) - assert.NoErr(err) // Writing file should succeed + if err := ioutil.WriteFile(testPath, []byte(tmplNewGold), os.ModePerm); err != nil { + t.Logf("could not write file: %v\n", err) + t.FailNow() + } - err = tmpl.Execute(destDir, true, false) - assert.NoErr(err) // Should execute template + if err := tmpl.Execute(destDir, true, false); err != nil { + t.Logf("could not execute template: %v\n", err) + t.FailNow() + } - contents, err = os.ReadFile(testPath) - assert.NoErr(err) // Should be able to read file - assert.Equal(string(contents), tmplNewGold) // Template should match new golden file + 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() + } } diff --git a/schema/convert.go b/schema/convert.go deleted file mode 100644 index 03ff44c69d353c59789d1678cfd290de45b2da04..0000000000000000000000000000000000000000 --- a/schema/convert.go +++ /dev/null @@ -1,46 +0,0 @@ -package schema - -import ( - "fmt" - - "gopkg.in/yaml.v3" -) - -// Unmarshal YAML to map[string]any instead of map[any]any. -func Unmarshal(in []byte, out any) error { - var res any - - if err := yaml.Unmarshal(in, &res); err != nil { - return err - } - *out.(*any) = mapValue(res) - - return nil -} - -func mapSlice(in []any) []any { - res := make([]any, len(in)) - for i, v := range in { - res[i] = mapValue(v) - } - return res -} - -func mapMap(in map[any]any) map[string]any { - res := make(map[string]any) - for k, v := range in { - res[fmt.Sprintf("%v", k)] = mapValue(v) - } - return res -} - -func mapValue(v any) any { - switch v := v.(type) { - case []any: - return mapSlice(v) - case map[any]any: - return mapMap(v) - default: - return v - } -} diff --git a/schema/schema.go b/schema/schema.go deleted file mode 100644 index 7f925d9a56e69d85dc96643821da9a080b3bcd24..0000000000000000000000000000000000000000 --- a/schema/schema.go +++ /dev/null @@ -1,49 +0,0 @@ -package schema - -import ( - _ "embed" - "fmt" - "io" - "strings" - - "github.com/xeipuuv/gojsonschema" -) - -var ( - //go:embed tmpl.json - schema []byte - schemaLoader = gojsonschema.NewBytesLoader(schema) -) - -// Lint is for linting a recipe against the schema -func Lint(r io.Reader) error { - data, err := io.ReadAll(r) - if err != nil { - return err - } - var m any - if err := Unmarshal(data, &m); err != nil { - return err - } - sourceLoader := gojsonschema.NewGoLoader(m) - result, err := gojsonschema.Validate(schemaLoader, sourceLoader) - if err != nil { - return err - } - if len(result.Errors()) > 0 { - return ResultErrors(result.Errors()) - } - return nil -} - -// ResultErrors is a slice of gojsonschema.ResultError that implements error -type ResultErrors []gojsonschema.ResultError - -// Error implements error -func (r ResultErrors) Error() string { - errs := make([]string, 0, len(r)) - for _, re := range r { - errs = append(errs, fmt.Sprintf("%s: %s", re.Field(), re.Description())) - } - return strings.Join(errs, " | ") -} diff --git a/schema/tmpl.json b/schema/tmpl.json deleted file mode 100644 index b8acf9826e47b572262112985237ebeeb86d3797..0000000000000000000000000000000000000000 --- a/schema/tmpl.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://git.jojodev.com/jolheiser/tmpl/src/branch/main/schema/tmpl.json", - "title": "tmpl template", - "description": "A template for tmpl", - "type": "object", - "required": [ - "prompts" - ], - "additionalProperties": false, - "properties": { - "prompts": { - "description": "Template prompts", - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "required": [ - "id" - ], - "additionalProperties": false, - "properties": { - "id": { - "description": "The unique prompt ID", - "type": "string" - }, - "label": { - "description": "A label to show instead of the ID when prompting", - "type": "string" - }, - "default": { - "description": "A default value for the prompt", - "type": "string" - }, - "help": { - "description": "A help message for more information on a prompt", - "type": "string" - }, - "depends_on": { - "description": "A list of prompt IDs that this prompt depends on", - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - } - } - } - } -}