package vfs import ( "io" "io/ioutil" "os" "path/filepath" "github.com/spf13/afero" ) // CopyDir represents a directory that is mimicked on hard drive. type CopyDir interface { Fs() afero.Fs Retrieve(name string) (string, error) Path(name string) string Open(name string) (*os.File, error) Destroy() error } var _ CopyDir = ©Dir{} type copyDir struct { fs afero.Fs path string } func NewCopyDir(fs afero.Fs) (CopyDir, error) { dir, err := ioutil.TempDir("", "vfsCopy") if nil != err { return nil, err } return ©Dir{fs, dir}, nil } func (d *copyDir) Fs() afero.Fs { return d.fs } func (d *copyDir) Retrieve(name string) (string, error) { var path = d.Path(name) if _, err := os.Stat(path); os.IsNotExist(err) { var dir = filepath.Dir(path) os.MkdirAll(dir, 0744) dst, err := os.Create(path) if nil != err { return path, err } defer dst.Close() src, err := d.fs.Open(name) if nil != err { return path, err } defer src.Close() _, err = io.Copy(dst, src) if nil != err { return path, err } } return path, nil } func (d *copyDir) Path(name string) string { return filepath.Join(d.path, name) } func (d *copyDir) Open(name string) (*os.File, error) { path, err := d.Retrieve(name) if nil != err { return nil, err } return os.Open(path) } func (d *copyDir) Destroy() error { return os.RemoveAll(d.path) }