Skip to content

Commit

Permalink
Merge pull request #51 from pdrum/protect-output-on-err
Browse files Browse the repository at this point in the history
bug: Prevent wiping down output file on error.
  • Loading branch information
pdrum authored Aug 30, 2018
2 parents 758fd2f + 8ba4bf8 commit 40525ed
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 17 deletions.
28 changes: 11 additions & 17 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import (
"io/ioutil"
"net/http"
"os"
"path"
"strings"

"github.com/cheekybits/genny/out"
"github.com/cheekybits/genny/parse"
)

Expand Down Expand Up @@ -61,22 +61,7 @@ func main() {
fatal(exitcodeInvalidTypeSet, err)
}

var outWriter io.Writer
if len(*out) > 0 {
err := os.MkdirAll(path.Dir(*out), 0755)
if err != nil {
fatal(exitcodeDestFileFailed, err)
}

outFile, err := os.Create(*out)
if err != nil {
fatal(exitcodeDestFileFailed, err)
}
defer outFile.Close()
outWriter = outFile
} else {
outWriter = os.Stdout
}
outWriter := newWriter(*out)

if strings.ToLower(args[0]) == "get" {
if len(args) != 3 {
Expand Down Expand Up @@ -139,6 +124,15 @@ Flags:`)
flag.PrintDefaults()
}

func newWriter(fileName string) io.Writer {
if fileName == "" {
return os.Stdout
}
lf := &out.LazyFile{FileName: fileName}
defer lf.Close()
return lf
}

func fatal(code int, a ...interface{}) {
fmt.Println(a...)
os.Exit(code)
Expand Down
38 changes: 38 additions & 0 deletions out/lazy_file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package out

import (
"os"
"path"
)

// LazyFile is an io.WriteCloser which defers creation of the file it is supposed to write in
// till the first call to its write function in order to prevent creation of file, if no write
// is supposed to happen.
type LazyFile struct {
FileName string
written []byte
file *os.File
}

// Close closes the file if it is created. Returns nil if no file is created.
func (lw *LazyFile) Close() error {
if lw.file != nil {
return lw.file.Close()
}
return nil
}

// Write writes to the specified file and creates the file first time it is called.
func (lw *LazyFile) Write(p []byte) (int, error) {
if lw.file == nil {
err := os.MkdirAll(path.Dir(lw.FileName), 0755)
if err != nil {
return 0, err
}
lw.file, err = os.Create(lw.FileName)
if err != nil {
return 0, err
}
}
return lw.file.Write(p)
}
47 changes: 47 additions & 0 deletions out/lazy_file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package out_test

import (
"github.com/cheekybits/genny/out"
"github.com/stretchr/testify/assert"
"io/ioutil"
"os"
"testing"
)

const testFileName = "test-file.go"

func tearDown() {
var err = os.Remove(testFileName)
if err != nil && !os.IsNotExist(err) {
panic("Could not delete test file")
}
}

func assertFileContains(t *testing.T, expected string) {
file, err := os.Open(testFileName)
if err != nil {
panic(err)
}
fileBytes, err := ioutil.ReadAll(file)
if err != nil {
panic(err)
}
assert.Equal(t, expected, string(fileBytes), "File contents not written properly")
}

func TestMultipleWrites(t *testing.T) {
defer tearDown()
lf := out.LazyFile{FileName: testFileName}
defer lf.Close()
lf.Write([]byte("Word1"))
lf.Write([]byte("Word2"))
assertFileContains(t, "Word1Word2")
}

func TestNoWrite(t *testing.T) {
defer tearDown()
lf := out.LazyFile{FileName: testFileName}
defer lf.Close()
_, err := os.Stat(testFileName)
assert.True(t, os.IsNotExist(err), "Expected file not to be created")
}

0 comments on commit 40525ed

Please sign in to comment.