Skip to content

Commit

Permalink
Improve template errors (#504)
Browse files Browse the repository at this point in the history
Improve template errors
  • Loading branch information
twpayne committed Dec 4, 2019
2 parents 55ecebe + cf457c4 commit a23c640
Show file tree
Hide file tree
Showing 10 changed files with 43 additions and 34 deletions.
5 changes: 3 additions & 2 deletions cmd/secretbitwarden.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"

"github.com/spf13/cobra"
"github.com/twpayne/chezmoi/internal/chezmoi"
)

var bitwardenCmd = &cobra.Command{
Expand Down Expand Up @@ -46,11 +47,11 @@ func (c *Config) bitwardenFunc(args ...string) interface{} {
cmd.Stderr = os.Stderr
output, err := c.mutator.IdempotentCmdOutput(cmd)
if err != nil {
panic(fmt.Errorf("bitwarden: %s %s: %w\n%s", name, strings.Join(args, " "), err, output))
panic(fmt.Errorf("bitwarden: %s %s: %w\n%s", name, chezmoi.ShellQuoteArgs(args), err, output))
}
var data interface{}
if err := json.Unmarshal(output, &data); err != nil {
panic(fmt.Errorf("bitwarden: %s %s: %w\n%s", name, strings.Join(args, " "), err, output))
panic(fmt.Errorf("bitwarden: %s %s: %w\n%s", name, chezmoi.ShellQuoteArgs(args), err, output))
}
bitwardenCache[key] = data
return data
Expand Down
7 changes: 4 additions & 3 deletions cmd/secretgeneric.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strings"

"github.com/spf13/cobra"
"github.com/twpayne/chezmoi/internal/chezmoi"
)

var genericSecretCmd = &cobra.Command{
Expand Down Expand Up @@ -49,7 +50,7 @@ func (c *Config) secretFunc(args ...string) interface{} {
cmd.Stderr = os.Stderr
output, err := c.mutator.IdempotentCmdOutput(cmd)
if err != nil {
panic(fmt.Errorf("secret: %s %s: %w\n%s", name, strings.Join(args, " "), err, output))
panic(fmt.Errorf("secret: %s %s: %w\n%s", name, chezmoi.ShellQuoteArgs(args), err, output))
}
value := bytes.TrimSpace(output)
secretCache[key] = value
Expand All @@ -67,11 +68,11 @@ func (c *Config) secretJSONFunc(args ...string) interface{} {
cmd.Stderr = os.Stderr
output, err := c.mutator.IdempotentCmdOutput(cmd)
if err != nil {
panic(fmt.Errorf("secretJSON: %s %s: %w\n%s", name, strings.Join(args, " "), err, output))
panic(fmt.Errorf("secretJSON: %s %s: %w\n%s", name, chezmoi.ShellQuoteArgs(args), err, output))
}
var value interface{}
if err := json.Unmarshal(output, &value); err != nil {
panic(fmt.Errorf("secretJSON: %s %s: %w\n%s", name, strings.Join(args, " "), err, output))
panic(fmt.Errorf("secretJSON: %s %s: %w\n%s", name, chezmoi.ShellQuoteArgs(args), err, output))
}
secretJSONCache[key] = value
return value
Expand Down
4 changes: 2 additions & 2 deletions cmd/secretgopass.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"bytes"
"fmt"
"os/exec"
"strings"

"github.com/spf13/cobra"
"github.com/twpayne/chezmoi/internal/chezmoi"
)

var gopassCmd = &cobra.Command{
Expand Down Expand Up @@ -42,7 +42,7 @@ func (c *Config) gopassFunc(id string) string {
cmd := exec.Command(name, args...)
output, err := c.mutator.IdempotentCmdOutput(cmd)
if err != nil {
panic(fmt.Errorf("gopass: %s %s: %w", name, strings.Join(args, " "), err))
panic(fmt.Errorf("gopass: %s %s: %w", name, chezmoi.ShellQuoteArgs(args), err))
}
var password string
if index := bytes.IndexByte(output, '\n'); index != -1 {
Expand Down
7 changes: 4 additions & 3 deletions cmd/secretkeepassxc.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"strings"

"github.com/spf13/cobra"
"github.com/twpayne/chezmoi/internal/chezmoi"
"golang.org/x/crypto/ssh/terminal"
)

Expand Down Expand Up @@ -64,11 +65,11 @@ func (c *Config) keePassXCFunc(entry string) map[string]string {
args = append(args, c.KeePassXC.Database, entry)
output, err := c.runKeePassXCCLICommand(name, args)
if err != nil {
panic(fmt.Errorf("keepassxc: %s %s: %w", name, strings.Join(args, " "), err))
panic(fmt.Errorf("keepassxc: %s %s: %w", name, chezmoi.ShellQuoteArgs(args), err))
}
data, err := parseKeyPassXCOutput(output)
if err != nil {
panic(fmt.Errorf("keepassxc: %s %s: %w", name, strings.Join(args, " "), err))
panic(fmt.Errorf("keepassxc: %s %s: %w", name, chezmoi.ShellQuoteArgs(args), err))
}
keePassXCCache[entry] = data
return data
Expand All @@ -91,7 +92,7 @@ func (c *Config) keePassXCAttributeFunc(entry, attribute string) string {
args = append(args, c.KeePassXC.Database, entry)
output, err := c.runKeePassXCCLICommand(name, args)
if err != nil {
panic(fmt.Errorf("keepassxc: %s %s: %w", name, strings.Join(args, " "), err))
panic(fmt.Errorf("keepassxc: %s %s: %w", name, chezmoi.ShellQuoteArgs(args), err))
}
outputStr := strings.TrimSpace(string(output))
keePassXCAttributeCache[key] = outputStr
Expand Down
8 changes: 4 additions & 4 deletions cmd/secretonepassword.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"fmt"
"os"
"os/exec"
"strings"

"github.com/spf13/cobra"
"github.com/twpayne/chezmoi/internal/chezmoi"
)

var onepasswordCmd = &cobra.Command{
Expand Down Expand Up @@ -49,11 +49,11 @@ func (c *Config) onepasswordFunc(item string) interface{} {
cmd.Stderr = os.Stderr
output, err := c.mutator.IdempotentCmdOutput(cmd)
if err != nil {
panic(fmt.Errorf("onepassword: %s %s: %w\n%s", name, strings.Join(args, " "), err, output))
panic(fmt.Errorf("onepassword: %s %s: %w\n%s", name, chezmoi.ShellQuoteArgs(args), err, output))
}
var data interface{}
if err := json.Unmarshal(output, &data); err != nil {
panic(fmt.Errorf("onepassword: %s %s: %w\n%s", name, strings.Join(args, " "), err, output))
panic(fmt.Errorf("onepassword: %s %s: %w\n%s", name, chezmoi.ShellQuoteArgs(args), err, output))
}
onepasswordCache[item] = data
return data
Expand All @@ -70,7 +70,7 @@ func (c *Config) onepasswordDocumentFunc(item string) interface{} {
cmd.Stderr = os.Stderr
output, err := c.mutator.IdempotentCmdOutput(cmd)
if err != nil {
panic(fmt.Errorf("onepassword: %s %s: %w\n%s", name, strings.Join(args, " "), err, output))
panic(fmt.Errorf("onepassword: %s %s: %w\n%s", name, chezmoi.ShellQuoteArgs(args), err, output))
}
onepasswordDocumentCache[item] = string(output)
return string(output)
Expand Down
4 changes: 2 additions & 2 deletions cmd/secretpass.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"bytes"
"fmt"
"os/exec"
"strings"

"github.com/spf13/cobra"
"github.com/twpayne/chezmoi/internal/chezmoi"
)

var passCmd = &cobra.Command{
Expand Down Expand Up @@ -42,7 +42,7 @@ func (c *Config) passFunc(id string) string {
cmd := exec.Command(name, args...)
output, err := c.mutator.IdempotentCmdOutput(cmd)
if err != nil {
panic(fmt.Errorf("pass: %s %s: %w", name, strings.Join(args, " "), err))
panic(fmt.Errorf("pass: %s %s: %w", name, chezmoi.ShellQuoteArgs(args), err))
}
var password string
if index := bytes.IndexByte(output, '\n'); index != -1 {
Expand Down
6 changes: 3 additions & 3 deletions cmd/secretvault.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"fmt"
"os"
"os/exec"
"strings"

"github.com/spf13/cobra"
"github.com/twpayne/chezmoi/internal/chezmoi"
)

var vaultCmd = &cobra.Command{
Expand Down Expand Up @@ -45,11 +45,11 @@ func (c *Config) vaultFunc(key string) interface{} {
cmd.Stderr = os.Stderr
output, err := c.mutator.IdempotentCmdOutput(cmd)
if err != nil {
panic(fmt.Errorf("vault: %s %s: %w\n%s", name, strings.Join(args, " "), err, output))
panic(fmt.Errorf("vault: %s %s: %w\n%s", name, chezmoi.ShellQuoteArgs(args), err, output))
}
var data interface{}
if err := json.Unmarshal(output, &data); err != nil {
panic(fmt.Errorf("vault: %s %s: %w\n%s", name, strings.Join(args, " "), err, output))
panic(fmt.Errorf("vault: %s %s: %w\n%s", name, chezmoi.ShellQuoteArgs(args), err, output))
}
vaultCache[key] = data
return data
Expand Down
14 changes: 12 additions & 2 deletions internal/chezmoi/maybeshellquote.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package chezmoi

import (
"regexp"
"strings"
)

var needShellQuoteRegexp = regexp.MustCompile(`[^+\-./0-9A-Z_a-z]`)
Expand All @@ -11,8 +12,8 @@ const (
singleQuote = '\''
)

// maybeShellQuote returns s quoted as a shell argument, if necessary.
func maybeShellQuote(s string) string {
// MaybeShellQuote returns s quoted as a shell argument, if necessary.
func MaybeShellQuote(s string) string {
switch {
case s == "":
return "''"
Expand Down Expand Up @@ -49,3 +50,12 @@ func maybeShellQuote(s string) string {
return s
}
}

// ShellQuoteArgs returs args shell quoted and joined into a single string.
func ShellQuoteArgs(args []string) string {
shellQuotedArgs := make([]string, 0, len(args))
for _, arg := range args {
shellQuotedArgs = append(shellQuotedArgs, MaybeShellQuote(arg))
}
return strings.Join(shellQuotedArgs, " ")
}
2 changes: 1 addition & 1 deletion internal/chezmoi/maybeshellquote_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ func TestMaybeShellQuote(t *testing.T) {
`a/b`: `a/b`,
`a b`: `'a b'`,
} {
assert.Equal(t, expected, maybeShellQuote(s), "quoting %q", s)
assert.Equal(t, expected, MaybeShellQuote(s), "quoting %q", s)
}
}
20 changes: 8 additions & 12 deletions internal/chezmoi/verbosemutator.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func NewVerboseMutator(w io.Writer, m Mutator, colored bool) *VerboseMutator {

// Chmod implements Mutator.Chmod.
func (m *VerboseMutator) Chmod(name string, mode os.FileMode) error {
action := fmt.Sprintf("chmod %o %s", mode, maybeShellQuote(name))
action := fmt.Sprintf("chmod %o %s", mode, MaybeShellQuote(name))
err := m.m.Chmod(name, mode)
if err == nil {
_, _ = fmt.Fprintln(m.w, action)
Expand All @@ -58,7 +58,7 @@ func (m *VerboseMutator) IdempotentCmdOutput(cmd *exec.Cmd) ([]byte, error) {

// Mkdir implements Mutator.Mkdir.
func (m *VerboseMutator) Mkdir(name string, perm os.FileMode) error {
action := fmt.Sprintf("mkdir -m %o %s", perm, maybeShellQuote(name))
action := fmt.Sprintf("mkdir -m %o %s", perm, MaybeShellQuote(name))
err := m.m.Mkdir(name, perm)
if err == nil {
_, _ = fmt.Fprintln(m.w, action)
Expand All @@ -70,7 +70,7 @@ func (m *VerboseMutator) Mkdir(name string, perm os.FileMode) error {

// RemoveAll implements Mutator.RemoveAll.
func (m *VerboseMutator) RemoveAll(name string) error {
action := fmt.Sprintf("rm -rf %s", maybeShellQuote(name))
action := fmt.Sprintf("rm -rf %s", MaybeShellQuote(name))
err := m.m.RemoveAll(name)
if err == nil {
_, _ = fmt.Fprintln(m.w, action)
Expand All @@ -82,7 +82,7 @@ func (m *VerboseMutator) RemoveAll(name string) error {

// Rename implements Mutator.Rename.
func (m *VerboseMutator) Rename(oldpath, newpath string) error {
action := fmt.Sprintf("mv %s %s", maybeShellQuote(oldpath), maybeShellQuote(newpath))
action := fmt.Sprintf("mv %s %s", MaybeShellQuote(oldpath), MaybeShellQuote(newpath))
err := m.m.Rename(oldpath, newpath)
if err == nil {
_, _ = fmt.Fprintln(m.w, action)
Expand Down Expand Up @@ -111,7 +111,7 @@ func (m *VerboseMutator) Stat(name string) (os.FileInfo, error) {

// WriteFile implements Mutator.WriteFile.
func (m *VerboseMutator) WriteFile(name string, data []byte, perm os.FileMode, currData []byte) error {
action := fmt.Sprintf("install -m %o /dev/null %s", perm, maybeShellQuote(name))
action := fmt.Sprintf("install -m %o /dev/null %s", perm, MaybeShellQuote(name))
err := m.m.WriteFile(name, data, perm, currData)
if err == nil {
_, _ = fmt.Fprintln(m.w, action)
Expand Down Expand Up @@ -147,7 +147,7 @@ func (m *VerboseMutator) WriteFile(name string, data []byte, perm os.FileMode, c

// WriteSymlink implements Mutator.WriteSymlink.
func (m *VerboseMutator) WriteSymlink(oldname, newname string) error {
action := fmt.Sprintf("ln -sf %s %s", maybeShellQuote(oldname), maybeShellQuote(newname))
action := fmt.Sprintf("ln -sf %s %s", MaybeShellQuote(oldname), MaybeShellQuote(newname))
err := m.m.WriteSymlink(oldname, newname)
if err == nil {
_, _ = fmt.Fprintln(m.w, action)
Expand All @@ -159,15 +159,11 @@ func (m *VerboseMutator) WriteSymlink(oldname, newname string) error {

// cmdString returns a string representation of cmd.
func cmdString(cmd *exec.Cmd) string {
components := append([]string{cmd.Path}, cmd.Args[1:]...)
for i, component := range components {
components[i] = maybeShellQuote(component)
}
s := strings.Join(components, " ")
s := ShellQuoteArgs(append([]string{cmd.Path}, cmd.Args[1:]...))
if cmd.Dir == "" {
return s
}
return fmt.Sprintf("( cd %s && %s )", maybeShellQuote(cmd.Dir), s)
return fmt.Sprintf("( cd %s && %s )", MaybeShellQuote(cmd.Dir), s)
}

func isBinary(data []byte) bool {
Expand Down

0 comments on commit a23c640

Please sign in to comment.