From 7a1263ced6dfbea47b1a99f07b97d45cf03b4a36 Mon Sep 17 00:00:00 2001 From: Dave Henderson Date: Tue, 27 Nov 2018 23:08:08 -0500 Subject: Adding option to suppress empty output files Signed-off-by: Dave Henderson --- template.go | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) (limited to 'template.go') 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 +} -- cgit v1.2.3