diff --git a/disk.go b/disk.go index 5f8ea74..3221c21 100644 --- a/disk.go +++ b/disk.go @@ -3,6 +3,7 @@ package genny import ( "bytes" "io" + "io/fs" "os" "runtime" "sort" @@ -28,6 +29,24 @@ func (d *Disk) AddBox(box packd.Walker) error { }) } +func (d *Disk) AddFS(fsys fs.FS) error { + return fs.WalkDir(fsys, ".", func(path string, dir fs.DirEntry, err error) error { + if err != nil { + return err + } + if dir.IsDir() { + return nil + } + + file, err := fsys.Open(path) + if err != nil { + return err + } + d.Add(NewFile(path, file)) + return nil + }) +} + // Files returns a sorted list of all the files in the disk func (d *Disk) Files() []File { var files []File diff --git a/disk_test.go b/disk_test.go index 4b8efdf..33c37a0 100644 --- a/disk_test.go +++ b/disk_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/gobuffalo/genny/v2" + "github.com/gobuffalo/genny/v2/internal/testdata" "github.com/gobuffalo/packd" "github.com/stretchr/testify/require" ) @@ -128,3 +129,20 @@ func Test_Disk_AddBox(t *testing.T) { r.NoError(err) r.Equal("bar/baz.txt", f.Name()) } + +func Test_Disk_AddFS(t *testing.T) { + r := require.New(t) + + run := genny.DryRunner(context.Background()) + d := run.Disk + err := d.AddFS(testdata.Data()) + r.NoError(err) + + f, err := d.Find("foo.txt") + r.NoError(err) + r.Equal("foo.txt", f.Name()) + + f, err = d.Find("bar/baz.txt") + r.NoError(err) + r.Equal("bar/baz.txt", f.Name()) +} diff --git a/force.go b/force.go index f7790c1..a99ed99 100644 --- a/force.go +++ b/force.go @@ -2,6 +2,7 @@ package genny import ( "fmt" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -23,6 +24,30 @@ func ForceBox(g *Generator, box packd.Walker, force bool) error { }) } +// ForceFS will mount each file in the fs.FS and wrap it with ForceFile +func ForceFS(g *Generator, fsys fs.FS, force bool) error { + return fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if d.IsDir() { + return nil + } + r, err := fsys.Open(path) + if err != nil { + return err + } + f := NewFile(path, r) + ff := ForceFile(f, force) + f, err = ff(f) + if err != nil { + return err + } + g.File(f) + return nil + }) +} + // ForceFile is a TransformerFn that will return an error if the path exists if `force` is false. If `force` is true it will delete the path. func ForceFile(f File, force bool) TransformerFn { return func(f File) (File, error) { diff --git a/generator.go b/generator.go index 549bcd3..6815f2b 100644 --- a/generator.go +++ b/generator.go @@ -80,6 +80,7 @@ func (g *Generator) Box(box packd.Walker) error { }) } +// FS walks through a fs.FS and adds Files for each entry. func (g *Generator) FS(fsys fs.FS) error { return fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error { if err != nil { diff --git a/gentest/files.go b/gentest/files.go index 2654576..f8ac639 100644 --- a/gentest/files.go +++ b/gentest/files.go @@ -2,6 +2,8 @@ package gentest import ( "fmt" + "io/fs" + "io/ioutil" "path/filepath" "sort" "strings" @@ -35,7 +37,7 @@ func CompareFiles(exp []string, act []genny.File) error { } // CompareBox compares a packd.Walkable box of files (usually fixtures) -// the results of a genny.Runner +// to the results of a genny.Runner func CompareBox(exp packd.Walkable, res genny.Results) error { return exp.Walk(func(path string, file packd.File) error { if filepath.Base(path) == ".DS_Store" { @@ -52,6 +54,43 @@ func CompareBox(exp packd.Walkable, res genny.Results) error { }) } +// CompareFS compares a fs.FS of files (usually fixtures) to the results +// of a genny.Runner +func CompareFS(exp fs.FS, res genny.Results) error { + return fs.WalkDir(exp, ".", func(path string, d fs.DirEntry, err error) error { + if filepath.Base(path) == ".DS_Store" { + return nil + } + + if err != nil { + return err + } + if d.IsDir() { + return nil + } + + f, err := res.Find(path) + if err != nil { + return err + } + + file, err := exp.Open(path) + if err != nil { + return err + } + b, err := ioutil.ReadAll(file) + if err != nil { + return err + } + + if string(b) != f.String() { + return fmt.Errorf("[%s] expected %s to match %s", path, string(b), f) + } + + return nil + }) +} + // CompareBoxStripped compares a packd.Walkable box of files (usually fixtures) // the results of a genny.Runner by removing any whitespaces, tabs, or newlines. func CompareBoxStripped(exp packd.Walkable, res genny.Results) error { @@ -70,6 +109,42 @@ func CompareBoxStripped(exp packd.Walkable, res genny.Results) error { }) } +// CompareFSStripped compares a fs.FS (usually fixtures) to the results of a +// genny.Runner by removing any whitespaces, tabs, or newlines. +func CompareFSStripped(exp fs.FS, res genny.Results) error { + return fs.WalkDir(exp, ".", func(path string, d fs.DirEntry, err error) error { + if filepath.Base(path) == ".DS_Store" { + return nil + } + + if err != nil { + return err + } + if d.IsDir() { + return nil + } + + f, err := res.Find(path) + if err != nil { + return err + } + + file, err := exp.Open(path) + if err != nil { + return err + } + b, err := ioutil.ReadAll(file) + if err != nil { + return err + } + + if clean(string(b)) != clean(f.String()) { + return fmt.Errorf("[%s] expected %s to match %s", path, file, f) + } + return nil + }) +} + func clean(s string) string { s = strings.TrimSpace(s) s = strings.Replace(s, "\n", "", -1) diff --git a/gentest/files_test.go b/gentest/files_test.go index 89e77dc..3997c97 100644 --- a/gentest/files_test.go +++ b/gentest/files_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/gobuffalo/genny/v2" + "github.com/gobuffalo/genny/v2/internal/testdata" "github.com/gobuffalo/packd" "github.com/stretchr/testify/require" ) @@ -68,3 +69,41 @@ func Test_CompareBox_Stripped(t *testing.T) { r.NoError(CompareBoxStripped(box, res)) } + +func Test_CompareFS(t *testing.T) { + r := require.New(t) + + res := genny.Results{ + Files: []genny.File{ + genny.NewFileS("a.html", "A"), + genny.NewFileS("b.html", "B"), + }, + } + + r.NoError(CompareFS(testdata.BoxData(), res)) +} + +func Test_CompareFS_Missing(t *testing.T) { + r := require.New(t) + + res := genny.Results{ + Files: []genny.File{ + genny.NewFileS("b.html", "b"), + }, + } + + r.Error(CompareFS(testdata.BoxData(), res)) +} + +func Test_CompareFS_Stripped(t *testing.T) { + r := require.New(t) + + res := genny.Results{ + Files: []genny.File{ + genny.NewFileS("a.html", " A\n\r"), + genny.NewFileS("b.html", "B"), + }, + } + + r.NoError(CompareFSStripped(testdata.BoxData(), res)) +} diff --git a/internal/testdata/a.html b/internal/testdata/a.html new file mode 100644 index 0000000..8c7e5a6 --- /dev/null +++ b/internal/testdata/a.html @@ -0,0 +1 @@ +A \ No newline at end of file diff --git a/internal/testdata/b.html b/internal/testdata/b.html new file mode 100644 index 0000000..7371f47 --- /dev/null +++ b/internal/testdata/b.html @@ -0,0 +1 @@ +B \ No newline at end of file diff --git a/internal/testdata/testdata.go b/internal/testdata/testdata.go index 8f613da..f5fdcc7 100644 --- a/internal/testdata/testdata.go +++ b/internal/testdata/testdata.go @@ -11,3 +11,10 @@ var testdata embed.FS func Data() fs.FS { return testdata } + +//go:embed a.html b.html +var boxdata embed.FS + +func BoxData() fs.FS { + return boxdata +}