diff options
| author | Dave Henderson <dhenderson@gmail.com> | 2018-11-27 23:08:08 -0500 |
|---|---|---|
| committer | Dave Henderson <dhenderson@gmail.com> | 2018-11-27 23:15:49 -0500 |
| commit | 7a1263ced6dfbea47b1a99f07b97d45cf03b4a36 (patch) | |
| tree | ef38238691a362907a1a34cd3cb34bdd3de2ed50 /template.go | |
| parent | 64849331e9a42ebd6b57c1fc24dec20300a4c401 (diff) | |
Adding option to suppress empty output files
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
Diffstat (limited to 'template.go')
| -rw-r--r-- | template.go | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/template.go b/template.go index 86fbfb25..1741de10 100644 --- a/template.go +++ b/template.go @@ -1,6 +1,7 @@ package gomplate import ( + "bytes" "fmt" "io" "io/ioutil" @@ -8,6 +9,10 @@ import ( "path/filepath" "text/template" + "github.com/hairyhenderson/gomplate/conv" + "github.com/hairyhenderson/gomplate/env" + "github.com/pkg/errors" + "github.com/spf13/afero" ) @@ -219,9 +224,23 @@ func inList(list []string, entry string) bool { } func openOutFile(filename string, mode os.FileMode, modeOverride bool) (out io.WriteCloser, err error) { + if conv.ToBool(env.Getenv("GOMPLATE_SUPPRESS_EMPTY", "false")) { + out = newEmptySkipper(func() (io.WriteCloser, error) { + if filename == "-" { + return Stdout, nil + } + return createOutFile(filename, mode, modeOverride) + }) + return out, nil + } + if filename == "-" { return Stdout, nil } + return createOutFile(filename, mode, modeOverride) +} + +func createOutFile(filename string, mode os.FileMode, modeOverride bool) (out io.WriteCloser, err error) { out, err = fs.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode.Perm()) if err != nil { return out, err @@ -268,3 +287,67 @@ func executeCombinedGlob(globArray []string) ([]string, error) { return combinedExcludes, nil } + +// emptySkipper is a io.WriteCloser wrapper that will only start writing once a +// non-whitespace byte has been encountered. The writer must be provided by the +// `open` func +type emptySkipper struct { + open func() (io.WriteCloser, error) + + // internal + w io.WriteCloser + buf *bytes.Buffer + nw bool +} + +func newEmptySkipper(open func() (io.WriteCloser, error)) *emptySkipper { + return &emptySkipper{ + w: nil, + buf: &bytes.Buffer{}, + nw: false, + open: open, + } +} + +func (f *emptySkipper) Write(p []byte) (n int, err error) { + if !f.nw { + if allWhitespace(p) { + // buffer the whitespace + return f.buf.Write(p) + } + + // first time around, so open the writer + f.nw = true + f.w, err = f.open() + if err != nil { + return 0, err + } + if f.w == nil { + return 0, errors.New("nil writer returned by open") + } + // empty the buffer into the wrapped writer + _, err = f.buf.WriteTo(f.w) + if err != nil { + return 0, err + } + } + + return f.w.Write(p) +} + +func (f *emptySkipper) Close() error { + if f.w != nil { + return f.w.Close() + } + return nil +} + +func allWhitespace(p []byte) bool { + for _, b := range p { + if b == ' ' || b == '\t' || b == '\n' || b == '\r' || b == '\v' { + continue + } + return false + } + return true +} |
