diff --git a/README.md b/README.md index 7486ffb..18209bf 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Optionally, `ep` can: * dry-run (`-d` flag): output to stdout instead of replacing values inline * strict (`-s` flag): refuse to fallback to default values * verbose (`-v` flag): be verbose about it's operations +* charset (`-c` flag): specify a custom charset to replace variables. Example: `/usr/local/bin/ep -c iso8859-1 *.conf` `ep` can also `exec()` another command by passing diff --git a/bin/ep.go b/bin/ep.go index 44b5905..c8946ed 100644 --- a/bin/ep.go +++ b/bin/ep.go @@ -7,6 +7,7 @@ import ( "syscall" "github.com/kreuzwerker/envplate" + _ "github.com/paulrosania/go-charset/data" "github.com/spf13/cobra" "github.com/yawn/doubledash" ) @@ -27,6 +28,7 @@ func main() { dryRun *bool strict *bool verbose *bool + charset *string ) root := &cobra.Command{ @@ -38,9 +40,10 @@ func main() { Run: func(cmd *cobra.Command, args []string) { var h = envplate.Handler{ - Backup: *backup, - DryRun: *dryRun, - Strict: *strict, + Backup: *backup, + DryRun: *dryRun, + Strict: *strict, + Charset: *charset, } if err := h.Apply(args); err != nil { @@ -67,6 +70,7 @@ func main() { dryRun = root.Flags().BoolP("dry-run", "d", false, "Dry-run - output templates to stdout instead of inline replacement") strict = root.Flags().BoolP("strict", "s", false, "Strict-mode - fail when falling back on defaults") verbose = root.Flags().BoolP("verbose", "v", false, "Verbose logging") + charset = root.Flags().StringP("charset", "c", "", "Output charset") if err := root.Execute(); err != nil { log.Fatalf("Failed to start the application: %v", err) diff --git a/envplate.go b/envplate.go index 2a146e9..b715ea2 100644 --- a/envplate.go +++ b/envplate.go @@ -1,10 +1,13 @@ package envplate import ( + "bytes" + "fmt" "os" "path/filepath" "regexp" + "github.com/paulrosania/go-charset/charset" "github.com/yawn/envmap" ) @@ -14,9 +17,10 @@ const ( ) type Handler struct { - Backup bool - DryRun bool - Strict bool + Backup bool + DryRun bool + Strict bool + Charset string } var exp = regexp.MustCompile(`(\\*)\$\{(.+?)(?:(\:\-)(.*?))?\}`) @@ -85,7 +89,12 @@ func (h *Handler) parse(file string) error { errors = append(errors, Log(ERROR, "Tried to escape '%s', but was no escape sequence", content)) } - return escaped + encodedValue, err := convertToCharset(escaped, h.Charset) + if err != nil { + errors = append(errors, Log(ERROR, "Tried to convert string '%s' to charset '%s' but an error ocourred: %v", encodedValue, h.Charset, err)) + return value + } + return encodedValue } @@ -112,7 +121,12 @@ func (h *Handler) parse(file string) error { value = esc[:len(esc)/2] + value } - return value + encodedValue, err := convertToCharset(value, h.Charset) + if err != nil { + errors = append(errors, Log(ERROR, "Tried to convert string '%s' to charset '%s' but an error ocourred: %v", encodedValue, h.Charset, err)) + return value + } + return encodedValue }) @@ -135,20 +149,42 @@ func (h *Handler) parse(file string) error { } - mode, err := filemode(file) - - if err != nil { + if err := saveFile(file, parsed, h.Charset); err != nil { return err } - if err := os.WriteFile(file, []byte(parsed), mode); err != nil { - return err - } + } + + return nil +} + +func saveFile(file string, parsed string, cs string) error { + mode, err := filemode(file) + if err != nil { + return err + } + + if err := os.WriteFile(file, []byte(parsed), mode); err != nil { + return err } return nil +} + +func convertToCharset(data string, charSet string) (string, error) { + if charSet == "" { + return data, nil + } + buf := new(bytes.Buffer) + w, err := charset.NewWriter(charSet, buf) + if err != nil { + return "", err + } + fmt.Fprintf(w, data) + w.Close() + return buf.String(), nil } func capture(s string) (esc, key, sep, def string) { diff --git a/go.mod b/go.mod index db04466..3d4e400 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/pflag v1.0.5 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 7e31144..3784d5c 100644 --- a/go.sum +++ b/go.sum @@ -197,6 +197,8 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c h1:P6XGcuPTigoHf4TSu+3D/7QOQ1MbL6alNwrGhcW7sKw= +github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c/go.mod h1:YnNlZP7l4MhyGQ4CBRwv6ohZTPrUJJZtEv4ZgADkbs4= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=