Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: 2
jobs:
test:
docker:
- image: circleci/golang:1.12
- image: circleci/golang:1.17
steps:
- checkout
- run: go test ./...
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ fmt.Println(err)

## WriteFile

`WriteFile()` writes the contents of the pipe to a named file. It returns the number of bytes written, or an error:
`WriteFile()` writes the contents of the pipe to a named file, truncating it if it exists. It returns the number of bytes written, or an error:

```go
var wrote int
Expand Down
9 changes: 5 additions & 4 deletions sinks.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,12 @@ func (p *Pipe) String() (string, error) {
}

// WriteFile writes the contents of the Pipe to the specified file, and closes
// the pipe after reading. It returns the number of bytes successfully written,
// or an error. If there is an error reading or writing, the pipe's error status
// is also set.
// the pipe after reading. If the file already exists, it is truncated and the
// new data will replace the old. It returns the number of bytes successfully
// written, or an error. If there is an error reading or writing, the pipe's
// error status is also set.
func (p *Pipe) WriteFile(fileName string) (int64, error) {
return p.writeOrAppendFile(fileName, os.O_RDWR|os.O_CREATE)
return p.writeOrAppendFile(fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC)
}

func (p *Pipe) writeOrAppendFile(fileName string, mode int) (int64, error) {
Expand Down
66 changes: 47 additions & 19 deletions sinks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package script

import (
"bytes"
"github.com/google/go-cmp/cmp"
"io/ioutil"
"os"
"testing"

"github.com/google/go-cmp/cmp"
)

// doSinksOnPipe calls every kind of sink method on the supplied pipe and
Expand Down Expand Up @@ -61,20 +62,19 @@ func doSinksOnPipe(t *testing.T, p *Pipe, kind string) {
func TestAppendFile(t *testing.T) {
t.Parallel()
orig := "Hello, world"
testFile := "testdata/appendfile.txt"
defer os.Remove(testFile)
path := t.TempDir() + t.Name()
// ignore results; we're testing AppendFile, not WriteFile
_, _ = Echo(orig).WriteFile(testFile)
_, _ = Echo(orig).WriteFile(path)
extra := " and goodbye"
wrote, err := Echo(extra).AppendFile(testFile)
wrote, err := Echo(extra).AppendFile(path)
if err != nil {
t.Error(err)
}
if int(wrote) != len(extra) {
t.Errorf("want %d bytes written, got %d", len(extra), int(wrote))
}
// check file contains both contents
got, err := File(testFile).String()
got, err := File(path).String()
if err != nil {
t.Error(err)
}
Expand Down Expand Up @@ -180,7 +180,7 @@ func TestSliceSink(t *testing.T) {
wantErr bool
}{
{
name: "Multiple lines pipe",
name: "Multiple lines pipe",
fields: Echo("testdata/multiple_files/1.txt\ntestdata/multiple_files/2.txt\ntestdata/multiple_files/3.tar.zip\n"),
want: []string{
"testdata/multiple_files/1.txt",
Expand All @@ -190,19 +190,19 @@ func TestSliceSink(t *testing.T) {
wantErr: false,
},
{
name: "Empty pipe",
fields: Echo(""),
want: []string{},
name: "Empty pipe",
fields: Echo(""),
want: []string{},
wantErr: false,
},
{
name: "Single newline",
fields: Echo("\n"),
want: []string{""},
name: "Single newline",
fields: Echo("\n"),
want: []string{""},
wantErr: false,
},
{
name: "Empty line between two existing lines",
name: "Empty line between two existing lines",
fields: Echo("testdata/multiple_files/1.txt\n\ntestdata/multiple_files/3.tar.zip"),
want: []string{
"testdata/multiple_files/1.txt",
Expand Down Expand Up @@ -297,23 +297,51 @@ func TestString(t *testing.T) {
}
}

func TestWriteFile(t *testing.T) {
func TestWriteFileNew(t *testing.T) {
t.Parallel()
want := "Hello, world"
testFile := "testdata/writefile.txt"
defer os.Remove(testFile)
wrote, err := Echo(want).WriteFile(testFile)
path := t.TempDir() + t.Name()
wrote, err := Echo(want).WriteFile(path)
if err != nil {
t.Error(err)
}
if int(wrote) != len(want) {
t.Errorf("want %d bytes written, got %d", len(want), int(wrote))
}
got, err := File(testFile).String()
got, err := File(path).String()
if err != nil {
t.Error(err)
}
if got != want {
t.Errorf("want %q, got %q", want, got)
}
}

func TestWriteFileTruncatesExisting(t *testing.T) {
t.Parallel()
want := "Hello, world"
path := t.TempDir() + t.Name()
// write some data first so we can check for truncation
data := make([]byte, 15)
err := os.WriteFile(path, data, 0600)
if err != nil {
t.Fatal(err)
}
wrote, err := Echo(want).WriteFile(path)
if err != nil {
t.Error(err)
}
if int(wrote) != len(want) {
t.Errorf("want %d bytes written, got %d", len(want), int(wrote))
}
got, err := File(path).String()
if err != nil {
t.Error(err)
}
if got == want+"\x00\x00\x00" {
t.Fatalf("file not truncated on write")
}
if got != want {
t.Errorf("want %q, got %q", want, got)
}
}