go-billy
go-billy copied to clipboard
memfs OpenFile does not work on directories
After finally getting a wrapper basically working, I run into an issue because memfs's OpenFile won't open directories. That's not how anything works.
I would strongly encourage you to replace all usage of go-billy with afero, as it fully and properly implements an os
"compatible" filesystem abstraction. That said, thank you for your time and effort in this library (though more so with go-git).
I found a workaround for the wrapper, but I still think y'all should release yourself from this project.
package main
import (
"errors"
"io"
"os"
"time"
"github.com/spf13/afero"
billy "gopkg.in/src-d/go-billy.v3"
"gopkg.in/src-d/go-billy.v3/memfs"
)
var ErrNotImplemented = errors.New("not implemented")
type billyToAferoFile struct {
billy.File
fs billy.Filesystem
path string
}
func (f *billyToAferoFile) WriteAt(p []byte, off int64) (n int, err error) {
return 0, ErrNotImplemented
}
func (f *billyToAferoFile) Readdir(n int) ([]os.FileInfo, error) {
// TODO: implement n
return f.fs.ReadDir(f.path)
}
func (f *billyToAferoFile) Readdirnames(n int) ([]string, error) {
// TODO: implement n
files, err := f.fs.ReadDir(f.path)
if err != nil {
return nil, err
}
var names []string
for _, info := range files {
names = append(names, info.Name())
}
return names, nil
}
func (f *billyToAferoFile) Stat() (os.FileInfo, error) {
return f.fs.Stat(f.path)
}
func (f *billyToAferoFile) Sync() error {
return nil
}
func (f *billyToAferoFile) Truncate(size int64) error {
return ErrNotImplemented
}
func (f *billyToAferoFile) WriteString(s string) (ret int, err error) {
return io.WriteString(f, s)
}
type billyToAferoFs struct {
billy.Filesystem
}
func (fs *billyToAferoFs) Name() string {
return "billy.Filesystem"
}
func (fs *billyToAferoFs) RemoveAll(path string) error {
return fs.Remove(path)
}
func (fs *billyToAferoFs) Mkdir(name string, perm os.FileMode) error {
return fs.MkdirAll(name, perm)
}
func (fs *billyToAferoFs) Chmod(name string, mode os.FileMode) error {
return nil
}
func (fs *billyToAferoFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
return nil
}
func (fs *billyToAferoFs) Create(name string) (afero.File, error) {
f, err := fs.Filesystem.Create(name)
return &billyToAferoFile{f, fs.Filesystem, name}, err
}
func (fs *billyToAferoFs) Open(name string) (afero.File, error) {
info, _ := fs.Filesystem.Stat(name)
if info.IsDir() {
f, err := memfs.New().Create(name)
return &billyToAferoFile{f, fs.Filesystem, name}, err
}
f, err := fs.Filesystem.Open(name)
return &billyToAferoFile{f, fs.Filesystem, name}, err
}
func (fs *billyToAferoFs) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) {
info, _ := fs.Filesystem.Stat(name)
if info.IsDir() {
f, err := memfs.New().Create(name)
return &billyToAferoFile{f, fs.Filesystem, name}, err
}
f, err := fs.Filesystem.OpenFile(name, flag, perm)
return &billyToAferoFile{f, fs.Filesystem, name}, err
}
@progrium Thanks for sharing the wrapper, that might be useful to others.
Contributions are welcome, so if anyone is willing to work on improving memfs, that will be welcome. I have changed the title of the issue accordingly.