From 9cf3376cb3e4450a34c14ba8280a808a1422fb0f Mon Sep 17 00:00:00 2001 From: Manuel Vogel Date: Tue, 19 Oct 2021 17:30:35 +0300 Subject: [PATCH] feat: add charset flag --- README.md | 1 + bin/ep.go | 10 ++++++--- envplate.go | 60 ++++++++++++++++++++++++++++++++++++++++++----------- go.mod | 1 + go.sum | 2 ++ 5 files changed, 59 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 57d10a9..c59f37b 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 7848600..463443b 100644 --- a/envplate.go +++ b/envplate.go @@ -1,11 +1,14 @@ package envplate import ( + "bytes" + "fmt" "io/ioutil" "os" "path/filepath" "regexp" + "github.com/paulrosania/go-charset/charset" "github.com/yawn/envmap" ) @@ -15,9 +18,10 @@ const ( ) type Handler struct { - Backup bool - DryRun bool - Strict bool + Backup bool + DryRun bool + Strict bool + Charset string } var exp = regexp.MustCompile(`(\\*)\$\{(.+?)(?:(\:\-)(.*?))?\}`) @@ -86,7 +90,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 } @@ -113,7 +122,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 }) @@ -132,13 +146,7 @@ func (h *Handler) parse(file string) error { } - mode, err := filemode(file) - - if err != nil { - return err - } - - if err := ioutil.WriteFile(file, []byte(parsed), mode); err != nil { + if err := saveFile(file, parsed, h.Charset); err != nil { return err } @@ -152,6 +160,34 @@ func (h *Handler) parse(file string) error { } +func saveFile(file string, parsed string, cs string) error { + mode, err := filemode(file) + if err != nil { + return err + } + + if err := ioutil.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) { matches := exp.FindStringSubmatch(s) diff --git a/go.mod b/go.mod index 923c122..661f949 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.0.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.0-20210107192922-496545a6307b // indirect diff --git a/go.sum b/go.sum index 7a9a4ac..c04b3c1 100644 --- a/go.sum +++ b/go.sum @@ -191,6 +191,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=