Skip to content

Commit

Permalink
feat: Add ExtendFS to take one FS and make a new one from it (#12)
Browse files Browse the repository at this point in the history
* feat: Add ExtendFS to take one FS and make a new one from it

This is particularly dandy in situations when you have something that
implements fs.FS but you can't write to it and you want a memoryfs.FS to
work with and add stuff too.
  • Loading branch information
owenrumney authored May 4, 2022
1 parent ed550ca commit 959a422
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
22 changes: 22 additions & 0 deletions fs.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package memoryfs

import (
"io"
"io/fs"
"io/ioutil"
"strings"
Expand Down Expand Up @@ -29,6 +30,27 @@ func New() *FS {
}
}

// CloneFS allows you to take on fs.FS and wrap it in an fs that is writable
func CloneFS(base fs.FS) *FS {
newFS := New()
fs.WalkDir(base, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}

if d.IsDir() {
return newFS.MkdirAll(path, d.Type().Perm())
}

// Lazy write the files, holding onto the base FS to read the content on demand
return newFS.WriteLazyFile(path, func() (io.Reader, error) {
return base.Open(path)
}, d.Type().Perm())
})

return newFS
}

// Stat returns a FileInfo describing the file.
func (m *FS) Stat(name string) (fs.FileInfo, error) {
name = cleanse(name)
Expand Down
21 changes: 21 additions & 0 deletions fs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,27 @@ func Test_WriteWhileOpen(t *testing.T) {
assert.Equal(t, "hello world", string(data))
}

func Test_CloneFS(t *testing.T) {
memfs := New()
require.NoError(t, memfs.WriteFile("file1.txt", []byte("This is the first file"), fs.ModePerm))
require.NoError(t, memfs.MkdirAll("/original/fs", fs.ModeDir))
require.NoError(t, memfs.WriteFile("original/fs/nested.txt", []byte("This is the nested file"), fs.ModePerm))

clone := CloneFS(memfs)
require.NoError(t, clone.WriteFile("second.txt", []byte("This is the second file"), fs.ModePerm))

for _, filename := range []string{"file1.txt", "/original/fs/nested.txt", "second.txt"} {
f, err := clone.Open(filename)
require.NoError(t, err)
defer func() { _ = f.Close() }()

data, err := ioutil.ReadAll(f)
require.NoError(t, err)
assert.NotNil(t, data)
}

}

func Test_MkdirAllRoot(t *testing.T) {
memfs := New()
err := memfs.MkdirAll(".", 0o644)
Expand Down

0 comments on commit 959a422

Please sign in to comment.