Major changes (#22)
1. Switch from TOML to YAML (oof) 2. Add a JSON schema for templates (anti-oof) 3. Add functionality for prompt defaults to be based on earlier prompt answers 4. Add env commands and setting/loading for tmpl-specific env 5. Use a more helpful testing library Co-authored-by: jolheiser <john.olheiser@gmail.com> Reviewed-on: #22pull/23/head v0.2.0
parent
4987bf8aed
commit
07ccb51584
12
CLI.md
12
CLI.md
|
@ -11,6 +11,10 @@ tmpl
|
|||
[--source|-s]=[value]
|
||||
```
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
Template automation
|
||||
|
||||
**Usage**:
|
||||
|
||||
```
|
||||
|
@ -36,6 +40,14 @@ Download a template
|
|||
|
||||
Show tmpl environment variables
|
||||
|
||||
### set, add
|
||||
|
||||
Set a tmpl environment variable (stored plaintext)
|
||||
|
||||
### unset, delete
|
||||
|
||||
Unsets a tmpl environment variable
|
||||
|
||||
## init
|
||||
|
||||
Initialize a template
|
||||
|
|
|
@ -6,34 +6,28 @@ This documentation aims to cover FAQs and setup.
|
|||
|
||||
A "valid" tmpl template only requires two things
|
||||
|
||||
1. A `template.toml` file in the root directory.
|
||||
1. A `tmpl.yaml` file in the root directory.
|
||||
2. A `template` directory that serves as the "root" of the template.
|
||||
|
||||
## template.toml
|
||||
## tmpl.yaml
|
||||
|
||||
**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}`.
|
||||
**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`.
|
||||
|
||||
```toml
|
||||
# Key-value pairs can be simple
|
||||
# The user will receive a basic prompt asking them to fill out the variable
|
||||
project = "my-project"
|
||||
```yaml
|
||||
# tmpl.yaml
|
||||
# Write any template args here to prompt the user for, giving any defaults/options as applicable
|
||||
|
||||
# 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"
|
||||
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
|
||||
|
@ -44,7 +38,7 @@ Everything in this directory (including paths and file names!) will be executed
|
|||
|
||||
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!)
|
||||
* 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
|
||||
|
@ -54,18 +48,20 @@ See the [documentation](https://golang.org/pkg/text/template/) for every availab
|
|||
|
||||
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/)|
|
||||
| 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
|
||||
|
|
@ -8,7 +8,7 @@ The two projects share many similarities, however other than general layout/stru
|
|||
|
||||
[CLI Docs](CLI.md)
|
||||
|
||||
[Project Docs/FAQs](DOCS.md)
|
||||
[Project Docs/FAQs](FAQ.md)
|
||||
|
||||
## Examples
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
"go.jolheiser.com/tmpl/cmd"
|
||||
)
|
||||
|
||||
//go:generate go run docs.go
|
||||
//go:generate go run cli.go
|
||||
func main() {
|
||||
app := cmd.NewApp()
|
||||
|
10
cmd/app.go
10
cmd/app.go
|
@ -4,8 +4,6 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"go.jolheiser.com/tmpl/cmd/flags"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
@ -13,12 +11,16 @@ import (
|
|||
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")
|
||||
|
@ -37,14 +39,14 @@ func NewApp() *cli.App {
|
|||
Usage: "Registry directory of tmpl",
|
||||
Value: defaultDir,
|
||||
DefaultText: "~/.tmpl",
|
||||
Destination: &flags.Registry,
|
||||
Destination: ®istryFlag,
|
||||
EnvVars: []string{"TMPL_REGISTRY"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "source",
|
||||
Aliases: []string{"s"},
|
||||
Usage: "Short-name source to use",
|
||||
Destination: &flags.Source,
|
||||
Destination: &sourceFlag,
|
||||
EnvVars: []string{"TMPL_SOURCE"},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"go.jolheiser.com/tmpl/cmd/flags"
|
||||
"go.jolheiser.com/tmpl/registry"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
|
@ -33,21 +32,21 @@ func runDownload(ctx *cli.Context) error {
|
|||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
|
||||
reg, err := registry.Open(flags.Registry)
|
||||
reg, err := registry.Open(registryFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var source *registry.Source
|
||||
if flags.Source != "" {
|
||||
if sourceFlag != "" {
|
||||
for _, s := range reg.Sources {
|
||||
if strings.EqualFold(s.Name, flags.Source) {
|
||||
if strings.EqualFold(s.Name, sourceFlag) {
|
||||
source = s
|
||||
break
|
||||
}
|
||||
}
|
||||
if source == nil {
|
||||
return fmt.Errorf("could not find source for %s", flags.Source)
|
||||
return fmt.Errorf("could not find source for %s", sourceFlag)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
69
cmd/env.go
69
cmd/env.go
|
@ -3,6 +3,8 @@ package cmd
|
|||
import (
|
||||
"os"
|
||||
|
||||
"go.jolheiser.com/tmpl/env"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
@ -12,20 +14,79 @@ var Env = &cli.Command{
|
|||
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("")
|
||||
log.Info().Str("TMPL_SOURCE", os.Getenv("TMPL_SOURCE")).Msg("system")
|
||||
|
||||
// Registry Path
|
||||
log.Info().Str("TMPL_REGISTRY", os.Getenv("TMPL_REGISTRY")).Msg("")
|
||||
log.Info().Str("TMPL_REGISTRY", os.Getenv("TMPL_REGISTRY")).Msg("system")
|
||||
|
||||
// Branch
|
||||
log.Info().Str("TMPL_BRANCH", os.Getenv("TMPL_BRANCH")).Msg("")
|
||||
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")
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
package flags
|
||||
|
||||
var (
|
||||
Registry string
|
||||
Source string
|
||||
)
|
17
cmd/init.go
17
cmd/init.go
|
@ -16,11 +16,11 @@ var Init = &cli.Command{
|
|||
}
|
||||
|
||||
func runInit(_ *cli.Context) error {
|
||||
if _, err := os.Lstat("template.toml"); !os.IsNotExist(err) {
|
||||
if _, err := os.Lstat("tmpl.yaml"); !os.IsNotExist(err) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return errors.New("template.toml already detected, aborting initialization")
|
||||
return errors.New("tmpl.yaml already detected, aborting initialization")
|
||||
}
|
||||
if fi, err := os.Lstat("template"); !os.IsNotExist(err) {
|
||||
if err != nil {
|
||||
|
@ -32,7 +32,7 @@ func runInit(_ *cli.Context) error {
|
|||
return errors.New("template directory already detected, aborting initialization")
|
||||
}
|
||||
|
||||
fi, err := os.Create("template.toml")
|
||||
fi, err := os.Create("tmpl.yaml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -46,11 +46,12 @@ func runInit(_ *cli.Context) error {
|
|||
return fi.Close()
|
||||
}
|
||||
|
||||
var comments = `# template.toml
|
||||
var comments = `# tmpl.yaml
|
||||
# Write any template args here to prompt the user for, giving any defaults/options as applicable
|
||||
|
||||
[name]
|
||||
prompt = "Project Name"
|
||||
help = "The name to use in the project"
|
||||
default = "tmpl"
|
||||
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
|
||||
`
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
"go.jolheiser.com/tmpl/cmd/flags"
|
||||
"go.jolheiser.com/tmpl/registry"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
@ -19,7 +18,7 @@ var List = &cli.Command{
|
|||
}
|
||||
|
||||
func runList(_ *cli.Context) error {
|
||||
reg, err := registry.Open(flags.Registry)
|
||||
reg, err := registry.Open(registryFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"go.jolheiser.com/tmpl/cmd/flags"
|
||||
"go.jolheiser.com/tmpl/registry"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
|
@ -21,7 +20,7 @@ func runRemove(ctx *cli.Context) error {
|
|||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
|
||||
reg, err := registry.Open(flags.Registry)
|
||||
reg, err := registry.Open(registryFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package cmd
|
|||
import (
|
||||
"os"
|
||||
|
||||
"go.jolheiser.com/tmpl/cmd/flags"
|
||||
"go.jolheiser.com/tmpl/registry"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
|
@ -18,7 +17,7 @@ var Restore = &cli.Command{
|
|||
}
|
||||
|
||||
func runRestore(_ *cli.Context) error {
|
||||
reg, err := registry.Open(flags.Registry)
|
||||
reg, err := registry.Open(registryFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package cmd
|
|||
import (
|
||||
"path/filepath"
|
||||
|
||||
"go.jolheiser.com/tmpl/cmd/flags"
|
||||
"go.jolheiser.com/tmpl/registry"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
|
@ -23,7 +22,7 @@ func runSave(ctx *cli.Context) error {
|
|||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
|
||||
reg, err := registry.Open(flags.Registry)
|
||||
reg, err := registry.Open(registryFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
"go.jolheiser.com/tmpl/cmd/flags"
|
||||
"go.jolheiser.com/tmpl/registry"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
|
@ -50,7 +49,7 @@ var (
|
|||
)
|
||||
|
||||
func runSourceList(_ *cli.Context) error {
|
||||
reg, err := registry.Open(flags.Registry)
|
||||
reg, err := registry.Open(registryFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -72,7 +71,7 @@ func runSourceAdd(ctx *cli.Context) error {
|
|||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
|
||||
reg, err := registry.Open(flags.Registry)
|
||||
reg, err := registry.Open(registryFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -91,7 +90,7 @@ func runSourceRemove(ctx *cli.Context) error {
|
|||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
|
||||
reg, err := registry.Open(flags.Registry)
|
||||
reg, err := registry.Open(registryFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
28
cmd/test.go
28
cmd/test.go
|
@ -1,9 +1,13 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"go.jolheiser.com/tmpl/schema"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
@ -23,15 +27,28 @@ func runTest(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
var errs []string
|
||||
if _, err := os.Lstat(filepath.Join(testPath, "template.toml")); err != nil {
|
||||
errs = append(errs, "could not find template.toml")
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
fi, err := os.Lstat(filepath.Join(testPath, "template"))
|
||||
fstat, err := os.Lstat(filepath.Join(testPath, "template"))
|
||||
if err != nil {
|
||||
errs = append(errs, "no template directory found")
|
||||
}
|
||||
if err == nil && !fi.IsDir() {
|
||||
if err == nil && !fstat.IsDir() {
|
||||
errs = append(errs, "template path is a file, not a directory")
|
||||
}
|
||||
|
||||
|
@ -41,6 +58,7 @@ func runTest(ctx *cli.Context) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
log.Info().Msg("this is a valid tmpl template")
|
||||
|
||||
log.Info().Msg("This is a valid tmpl template!")
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"go.jolheiser.com/tmpl/cmd/flags"
|
||||
"go.jolheiser.com/tmpl/registry"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
|
@ -21,7 +20,7 @@ func runUpdate(ctx *cli.Context) error {
|
|||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
|
||||
reg, err := registry.Open(flags.Registry)
|
||||
reg, err := registry.Open(registryFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
12
cmd/use.go
12
cmd/use.go
|
@ -1,7 +1,7 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"go.jolheiser.com/tmpl/cmd/flags"
|
||||
"go.jolheiser.com/tmpl/env"
|
||||
"go.jolheiser.com/tmpl/registry"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
|
@ -36,11 +36,19 @@ func runUse(ctx *cli.Context) error {
|
|||
dest = ctx.Args().Get(1)
|
||||
}
|
||||
|
||||
reg, err := registry.Open(flags.Registry)
|
||||
reg, err := registry.Open(registryFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
e, err := env.Load(registryFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.Set(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tmpl, err := reg.GetTemplate(ctx.Args().First())
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
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)
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
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 <path>/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 <path>/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)
|
||||
}
|
58
go.mod
58
go.mod
|
@ -1,15 +1,55 @@
|
|||
module go.jolheiser.com/tmpl
|
||||
|
||||
go 1.15
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/AlecAivazis/survey/v2 v2.2.2
|
||||
github.com/go-git/go-git/v5 v5.2.0
|
||||
github.com/AlecAivazis/survey/v2 v2.3.5
|
||||
github.com/go-git/go-git/v5 v5.4.2
|
||||
github.com/huandu/xstrings v1.3.2
|
||||
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
|
||||
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
|
||||
)
|
||||
|
|
242
go.sum
242
go.sum
|
@ -1,162 +1,202 @@
|
|||
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/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/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.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/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/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.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
|
||||
github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
|
||||
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/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/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
|
||||
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/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.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/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/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
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/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/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
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/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/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.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
|
||||
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
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/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.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
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-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
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/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
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/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/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/pgzip v1.2.4 h1:TQ7CNpYKovDOmqzRHKxJh0BeaBI7UdQZYc6p7pMQh1A=
|
||||
github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
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/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/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
||||
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/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.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/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/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
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/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/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/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/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/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.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/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/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
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/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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
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/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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
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/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/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
|
||||
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
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=
|
||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
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/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/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
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-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-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-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/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/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
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/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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
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=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/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=
|
||||
|
|
|
@ -23,11 +23,6 @@ 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
|
||||
}
|
||||
|
|
|
@ -9,8 +9,7 @@ import (
|
|||
"github.com/huandu/xstrings"
|
||||
)
|
||||
|
||||
var funcMap = map[string]interface{}{
|
||||
|
||||
var funcMap = map[string]any{
|
||||
// String conversions
|
||||
"upper": strings.ToUpper,
|
||||
"lower": strings.ToLower,
|
||||
|
@ -21,6 +20,12 @@ var funcMap = map[string]interface{}{
|
|||
"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
|
||||
"env": os.Getenv,
|
||||
|
|
|
@ -2,112 +2,97 @@ 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, "template.toml")
|
||||
if _, err := os.Lstat(templatePath); err != nil {
|
||||
templatePath := filepath.Join(dir, "tmpl.yaml")
|
||||
fi, err := os.Open(templatePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fi.Close()
|
||||
|
||||
templateBytes, err := ioutil.ReadFile(templatePath)
|
||||
cfg, err := config.Load(fi)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 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,
|
||||
}
|
||||
if tp.Label == "" {
|
||||
tp.Label = tp.ID
|
||||
}
|
||||
if tp.Default == nil {
|
||||
tp.Default = ""
|
||||
}
|
||||
prompts = append(prompts, tp)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// Sort the prompts so they are consistent
|
||||
sort.Sort(prompts)
|
||||
|
||||
for idx, prompt := range prompts {
|
||||
// Check for env variable
|
||||
if e, ok := os.LookupEnv(fmt.Sprintf("TMPL_VAR_%s", strings.ToUpper(prompt.Key))); ok {
|
||||
envKey := strings.ToUpper(prompt.ID)
|
||||
if e, ok := os.LookupEnv(fmt.Sprintf("TMPL_VAR_%s", envKey)); ok {
|
||||
prompts[idx].Value = e
|
||||
os.Setenv(fmt.Sprintf("TMPL_PROMPT_%s", envKey), e)
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if we are using defaults
|
||||
if defaults {
|
||||
prompts[idx].Value = prompt.Default
|
||||
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)
|
||||
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.Message,
|
||||
Message: prompt.Label,
|
||||
Options: t,
|
||||
Help: prompt.Help,
|
||||
}
|
||||
case bool:
|
||||
p = &survey.Confirm{
|
||||
Message: prompt.Message,
|
||||
Message: prompt.Label,
|
||||
Default: t,
|
||||
Help: prompt.Help,
|
||||
}
|
||||
case string:
|
||||
p = &survey.Input{
|
||||
Message: prompt.Message,
|
||||
Default: t,
|
||||
Message: prompt.Label,
|
||||
Default: os.ExpandEnv(t),
|
||||
Help: prompt.Help,
|
||||
}
|
||||
default:
|
||||
p = &survey.Input{
|
||||
Message: prompt.Message,
|
||||
Default: fmt.Sprintf("%v", t),
|
||||
Message: prompt.Label,
|
||||
Default: fmt.Sprint(t),
|
||||
Help: prompt.Help,
|
||||
}
|
||||
}
|
||||
|
@ -116,45 +101,36 @@ func prompt(dir string, defaults bool) (templatePrompts, error) {
|
|||
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]interface{} {
|
||||
m := make(map[string]interface{})
|
||||
func (t templatePrompts) ToMap() map[string]any {
|
||||
m := make(map[string]any)
|
||||
for _, p := range t {
|
||||
m[p.Key] = p.Value
|
||||
m[p.ID] = 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]interface{})
|
||||
m := make(map[string]any)
|
||||
for k, v := range t.ToMap() {
|
||||
vv := v // Enclosure
|
||||
m[k] = func() interface{} {
|
||||
m[k] = func() any {
|
||||
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]
|
||||
}
|
||||
|
|
|
@ -11,14 +11,14 @@ import (
|
|||
"github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/mholt/archiver/v3"
|
||||
"github.com/pelletier/go-toml"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Registry is a collection of Template
|
||||
type Registry struct {
|
||||
dir string
|
||||
Sources []*Source `toml:"sources"`
|
||||
Templates []*Template `toml:"templates"`
|
||||
Sources []*Source `yaml:"sources"`
|
||||
Templates []*Template `yaml:"templates"`
|
||||
}
|
||||
|
||||
func (r *Registry) save() error {
|
||||
|
@ -26,7 +26,7 @@ func (r *Registry) save() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := toml.NewEncoder(fi).Encode(r); err != nil {
|
||||
if err := yaml.NewEncoder(fi).Encode(r); err != nil {
|
||||
return err
|
||||
}
|
||||
return fi.Close()
|
||||
|
@ -34,7 +34,7 @@ func (r *Registry) save() error {
|
|||
|
||||
// MetaFilePath is the path to the Registry meta-file
|
||||
func (r *Registry) MetaFilePath() string {
|
||||
return filepath.Join(r.dir, "registry.toml")
|
||||
return filepath.Join(r.dir, "registry.yaml")
|
||||
}
|
||||
|
||||
// GetTemplate retrieves a Template from the Registry
|
||||
|
@ -111,7 +111,7 @@ func (r *Registry) RemoveTemplate(name string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// RemoveTemplate updates the Template on disk and in meta
|
||||
// UpdateTemplate 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 @@ func Open(dir string) (*Registry, error) {
|
|||
}
|
||||
}
|
||||
|
||||
tree, err := toml.LoadFile(reg.MetaFilePath())
|
||||
contents, err := os.ReadFile(reg.MetaFilePath())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := tree.Unmarshal(®); err != nil {
|
||||
if err := yaml.Unmarshal(contents, ®); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -254,9 +254,8 @@ func download(cloneURL, branch, dest string) error {
|
|||
}
|
||||
|
||||
func save(source, dest string) error {
|
||||
|
||||
// Make sure it's a valid template
|
||||
if _, err := os.Lstat(filepath.Join(source, "template.toml")); err != nil {
|
||||
if _, err := os.Lstat(filepath.Join(source, "tmpl.yaml")); err != nil {
|
||||
return err
|
||||
}
|
||||
fi, err := os.Lstat(filepath.Join(source, "template"))
|
||||
|
|
|
@ -1,26 +1,24 @@
|
|||
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()
|
||||
|
@ -30,9 +28,6 @@ func TestMain(m *testing.M) {
|
|||
|
||||
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)
|
||||
}
|
||||
|
@ -51,25 +46,22 @@ func TestTemplate(t *testing.T) {
|
|||
}
|
||||
|
||||
func testSave(t *testing.T) {
|
||||
if _, err := reg.SaveTemplate("test", tmplDir); err != nil {
|
||||
t.Log("could not save template")
|
||||
t.FailNow()
|
||||
}
|
||||
assert := is.New(t)
|
||||
_, err := reg.SaveTemplate("test", tmplDir)
|
||||
assert.NoErr(err) // Should save template
|
||||
}
|
||||
|
||||
func testGet(t *testing.T) {
|
||||
assert := is.New(t)
|
||||
_, err := reg.GetTemplate("test")
|
||||
if err != nil {
|
||||
t.Logf("could not get template")
|
||||
t.FailNow()
|
||||
}
|
||||
assert.NoErr(err) // Should get template
|
||||
}
|
||||
|
||||
func testGetFail(t *testing.T) {
|
||||
assert := is.New(t)
|
||||
_, err := reg.GetTemplate("fail")
|
||||
if !IsErrTemplateNotFound(err) {
|
||||
t.Logf("template should not exist")
|
||||
t.FailNow()
|
||||
if !errors.As(err, &ErrTemplateNotFound{}) {
|
||||
assert.Fail() // Template should not exist
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +73,7 @@ func setupTemplate() {
|
|||
}
|
||||
|
||||
// Template config
|
||||
fi, err := os.Create(filepath.Join(tmplDir, "template.toml"))
|
||||
fi, err := os.Create(filepath.Join(tmplDir, "tmpl.yaml"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@ import "fmt"
|
|||
// Source is a quick way to specify a git source
|
||||
// e.g. Gitea, GitHub, etc.
|
||||
type Source struct {
|
||||
Name string `toml:"name"`
|
||||
URL string `toml:"url"`
|
||||
Name string `yaml:"name"`
|
||||
URL string `yaml:"url"`
|
||||
}
|
||||
|
||||
// CloneURL constructs a URL suitable for cloning a repository
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
package registry
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/matryer/is"
|
||||
)
|
||||
|
||||
func TestSource(t *testing.T) {
|
||||
assert := is.New(t)
|
||||
|
||||
tt := []struct {
|
||||
Name string
|
||||
Source *Source
|
||||
|
@ -38,10 +41,7 @@ func TestSource(t *testing.T) {
|
|||
for _, tc := range tt {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
cloneURL := tc.Source.CloneURL(namespace)
|
||||
if !strings.EqualFold(tc.CloneURL, cloneURL) {
|
||||
t.Logf("incorrect clone URL:\n\tExpected: %s\n\tGot: %s\n", tc.CloneURL, cloneURL)
|
||||
t.Fail()
|
||||
}
|
||||
assert.Equal(tc.CloneURL, cloneURL) // Clone URLs should match
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,12 +15,12 @@ import (
|
|||
|
||||
// Template is a tmpl project
|
||||
type Template struct {
|
||||
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"`
|
||||
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"`
|
||||
}
|
||||
|
||||
// ArchiveName is the name given to the archive for this Template
|
||||
|
@ -51,7 +51,6 @@ func (t *Template) Execute(dest string, defaults, overwrite bool) error {
|
|||
}
|
||||
|
||||
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 {
|
||||
|
@ -117,8 +116,8 @@ func (t *Template) Execute(dest string, defaults, overwrite bool) error {
|
|||
})
|
||||
}
|
||||
|
||||
func mergeMaps(maps ...map[string]interface{}) map[string]interface{} {
|
||||
m := make(map[string]interface{})
|
||||
func mergeMaps(maps ...map[string]any) map[string]any {
|
||||
m := make(map[string]any)
|
||||
for _, mm := range maps {
|
||||
for k, v := range mm {
|
||||
m[k] = v
|
||||
|
|
|
@ -5,99 +5,74 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/matryer/is"
|
||||
)
|
||||
|
||||
var (
|
||||
tmplContents = `{{title name}} (@{{username}}) {{if .bool}}{{.year}}{{end}}`
|
||||
tmplContents = `{{title name}} (@{{username}}) {{if .bool}}{{.year}}{{end}} {{org}}`
|
||||
tmplTemplate = `
|
||||
name = "john olheiser"
|
||||
|
||||
[year]
|
||||
default = ${TMPL_TEST} # 2020
|
||||
|
||||
[package]
|
||||
default = "pkg"
|
||||
|
||||
[bool]
|
||||
default = true
|
||||
|
||||
[username]
|
||||
default = "username"
|
||||
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
|
||||
`
|
||||
tmplGold = "John Olheiser (@jolheiser) 2020"
|
||||
tmplGold = "John Olheiser (@jolheiser) 2020 jolheiser/org"
|
||||
tmplNewGold = "DO NOT OVERWRITE!"
|
||||
)
|
||||
|
||||
func testExecute(t *testing.T) {
|
||||
assert := is.New(t)
|
||||
destDir := t.TempDir()
|
||||
|
||||
// Set environment variable
|
||||
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()
|
||||
}
|
||||
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
|
||||
|
||||
// Get template
|
||||
tmpl, err := reg.GetTemplate("test")
|
||||
if err != nil {
|
||||
t.Logf("could not get template")
|
||||
t.FailNow()
|
||||
}
|
||||
assert.NoErr(err) // Should get template
|
||||
|
||||
// Execute template
|
||||
if err := tmpl.Execute(destDir, true, true); err != nil {
|
||||
t.Logf("could not execute template: %v\n", err)
|
||||
t.FailNow()
|
||||
}
|
||||
err = tmpl.Execute(destDir, true, true)
|
||||
assert.NoErr(err) // Should execute template
|
||||
|
||||
// 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()
|
||||
}
|
||||
assert.NoErr(err) // Should be able to read TEST file
|
||||
assert.Equal(string(contents), tmplGold) // Template should match golden file
|
||||
|
||||
// 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()
|
||||
}
|
||||
_, err = os.Lstat(pkgPath)
|
||||
assert.NoErr(err) // PKG directory should exist
|
||||
|
||||
// Check for .tmplkeep
|
||||
tmplKeep := filepath.Join(pkgPath, ".tmplkeep")
|
||||
if _, err := os.Lstat(tmplKeep); err == nil {
|
||||
t.Logf(".tmplkeep files should NOT be retained upon execution: %s\n", tmplKeep)
|
||||
t.FailNow()
|
||||
}
|
||||
_, err = os.Lstat(tmplKeep)
|
||||
assert.True(err != nil) // .tmplkeep file should NOT be retained
|
||||
|
||||
// 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()
|
||||
}
|
||||
err = ioutil.WriteFile(testPath, []byte(tmplNewGold), os.ModePerm)
|
||||
assert.NoErr(err) // Writing file should succeed
|
||||
|
||||
if err := tmpl.Execute(destDir, true, false); err != nil {
|
||||
t.Logf("could not execute template: %v\n", err)
|
||||
t.FailNow()
|
||||
}
|
||||
err = tmpl.Execute(destDir, true, false)
|
||||
assert.NoErr(err) // Should execute template
|
||||
|
||||
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()
|
||||
}
|
||||
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
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
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, " | ")
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
{
|
||||
"$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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue