From 15e0bd7d7d13f0ffdec795a8e04ac08ff88760d6 Mon Sep 17 00:00:00 2001 From: John Eikenberry Date: Thu, 23 Jul 2020 14:40:32 -0700 Subject: [PATCH] render initial file even when template is empty When first rendering a template to a file if the file doesn't exist and the evaluated template is empty, it wouldn't write the file to disk. It should always render the file to disk on successful template evaluation. --- renderer/renderer.go | 5 +- renderer/renderer_test.go | 117 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 2 deletions(-) diff --git a/renderer/renderer.go b/renderer/renderer.go index 59931c19e..366eab81d 100644 --- a/renderer/renderer.go +++ b/renderer/renderer.go @@ -60,11 +60,12 @@ type RenderResult struct { // whether it would have rendered and actually did render. func Render(i *RenderInput) (*RenderResult, error) { existing, err := ioutil.ReadFile(i.Path) - if err != nil && !os.IsNotExist(err) { + fileExists := !os.IsNotExist(err) + if err != nil && fileExists { return nil, errors.Wrap(err, "failed reading file") } - if bytes.Equal(existing, i.Contents) { + if bytes.Equal(existing, i.Contents) && fileExists { return &RenderResult{ DidRender: false, WouldRender: true, diff --git a/renderer/renderer_test.go b/renderer/renderer_test.go index 85f142ede..5d2052564 100644 --- a/renderer/renderer_test.go +++ b/renderer/renderer_test.go @@ -4,6 +4,7 @@ import ( "bytes" "io/ioutil" "os" + "path" "path/filepath" "testing" ) @@ -198,3 +199,119 @@ func TestAtomicWrite(t *testing.T) { contains(outFile.Name(), "second") }) } + +func TestRender(t *testing.T) { + t.Run("file-exists-same-content", func(t *testing.T) { + outDir, err := ioutil.TempDir("", "") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(outDir) + outFile, err := ioutil.TempFile(outDir, "") + if err != nil { + t.Fatal(err) + } + contents := []byte("first") + if _, err := outFile.Write(contents); err != nil { + t.Fatal(err) + } + path := outFile.Name() + if err = outFile.Close(); err != nil { + t.Fatal(err) + } + + rr, err := Render(&RenderInput{ + Path: path, + Contents: contents, + }) + if err != nil { + t.Fatal(err) + } + switch { + case rr.WouldRender && !rr.DidRender: + default: + t.Fatalf("Bad render results; would: %v, did: %v", + rr.WouldRender, rr.DidRender) + } + }) + t.Run("file-exists-diff-content", func(t *testing.T) { + outDir, err := ioutil.TempDir("", "") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(outDir) + outFile, err := ioutil.TempFile(outDir, "") + if err != nil { + t.Fatal(err) + } + contents := []byte("first") + if _, err := outFile.Write(contents); err != nil { + t.Fatal(err) + } + path := outFile.Name() + if err = outFile.Close(); err != nil { + t.Fatal(err) + } + + diff_contents := []byte("not-first") + rr, err := Render(&RenderInput{ + Path: path, + Contents: diff_contents, + }) + if err != nil { + t.Fatal(err) + } + switch { + case rr.WouldRender && rr.DidRender: + default: + t.Fatalf("Bad render results; would: %v, did: %v", + rr.WouldRender, rr.DidRender) + } + }) + t.Run("file-no-exists", func(t *testing.T) { + outDir, err := ioutil.TempDir("", "") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(outDir) + path := path.Join(outDir, "no-exists") + contents := []byte("first") + + rr, err := Render(&RenderInput{ + Path: path, + Contents: contents, + }) + if err != nil { + t.Fatal(err) + } + switch { + case rr.WouldRender && rr.DidRender: + default: + t.Fatalf("Bad render results; would: %v, did: %v", + rr.WouldRender, rr.DidRender) + } + }) + t.Run("empty-file-no-exists", func(t *testing.T) { + outDir, err := ioutil.TempDir("", "") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(outDir) + path := path.Join(outDir, "no-exists") + contents := []byte{} + + rr, err := Render(&RenderInput{ + Path: path, + Contents: contents, + }) + if err != nil { + t.Fatal(err) + } + switch { + case rr.WouldRender && rr.DidRender: + default: + t.Fatalf("Bad render results; would: %v, did: %v", + rr.WouldRender, rr.DidRender) + } + }) +}