Added afero proxy to ricefs.
Added mechanism to copy afero dir (temporarily) to a local directory.
This commit is contained in:
commit
dd37d56253
74
ricefs/file.go
Normal file
74
ricefs/file.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package ricefs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/GeertJohan/go.rice"
|
||||||
|
|
||||||
|
"github.com/spf13/afero"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ afero.File = &file{}
|
||||||
|
|
||||||
|
type file struct {
|
||||||
|
f *rice.File
|
||||||
|
info os.FileInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *file) Close() error { return f.f.Close() }
|
||||||
|
|
||||||
|
func (f *file) Read(p []byte) (int, error) { return f.f.Read(p) }
|
||||||
|
|
||||||
|
func (f *file) ReadAt(p []byte, off int64) (int, error) {
|
||||||
|
_, err := f.Seek(off, io.SeekStart)
|
||||||
|
if nil != err {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return f.Read(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *file) Seek(off int64, whence int) (int64, error) { return f.f.Seek(off, whence) }
|
||||||
|
|
||||||
|
func (f *file) Write(p []byte) (int, error) { return 0, ErrReadOnly }
|
||||||
|
|
||||||
|
func (f *file) WriteAt(p []byte, off int64) (int, error) { return 0, ErrReadOnly }
|
||||||
|
|
||||||
|
func (f *file) Name() string {
|
||||||
|
i, err := f.Stat()
|
||||||
|
if nil != err {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return i.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *file) Readdir(n int) ([]os.FileInfo, error) { return f.f.Readdir(n) }
|
||||||
|
|
||||||
|
func (f *file) Readdirnames(n int) ([]string, error) {
|
||||||
|
var dirs, err = f.Readdir(n)
|
||||||
|
if nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var names = make([]string, len(dirs))
|
||||||
|
for i, dir := range dirs {
|
||||||
|
names[i] = dir.Name()
|
||||||
|
}
|
||||||
|
return names, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *file) Stat() (os.FileInfo, error) {
|
||||||
|
if nil == f.info {
|
||||||
|
i, err := f.f.Stat()
|
||||||
|
if nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f.info = i
|
||||||
|
}
|
||||||
|
return f.info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *file) Sync() error { return ErrReadOnly }
|
||||||
|
|
||||||
|
func (f *file) Truncate(size int64) error { return ErrReadOnly }
|
||||||
|
|
||||||
|
func (f *file) WriteString(s string) (int, error) { return 0, ErrReadOnly }
|
84
ricefs/fs.go
Normal file
84
ricefs/fs.go
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
package ricefs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
rice "github.com/GeertJohan/go.rice"
|
||||||
|
"github.com/spf13/afero"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ afero.Fs = &RiceFs{}
|
||||||
|
|
||||||
|
func NewFs(b *rice.Box) *RiceFs {
|
||||||
|
return &RiceFs{b}
|
||||||
|
}
|
||||||
|
|
||||||
|
type RiceFs struct {
|
||||||
|
Box *rice.Box
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrReadOnly is returned when a write method is accessed.
|
||||||
|
var ErrReadOnly = errors.New("file system is read-only")
|
||||||
|
|
||||||
|
// ErrUseOpen is returned when trying to use OpenFile, use Open to open the (read-only) file.
|
||||||
|
var ErrUseOpen = errors.New("use Open method instead, non-read-only perms are not supported")
|
||||||
|
|
||||||
|
// Create is not supported for a RiceFs.
|
||||||
|
func (f *RiceFs) Create(name string) (afero.File, error) {
|
||||||
|
return nil, ErrReadOnly
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mkdir is not supported for a RiceFs.
|
||||||
|
func (f *RiceFs) Mkdir(name string, perm os.FileMode) error {
|
||||||
|
return ErrReadOnly
|
||||||
|
}
|
||||||
|
|
||||||
|
// MkdirAll is not supported for a RiceFs.
|
||||||
|
func (f *RiceFs) MkdirAll(path string, perm os.FileMode) error {
|
||||||
|
return ErrReadOnly
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open opens a file, returning it or an error, if any happens.
|
||||||
|
func (f *RiceFs) Open(name string) (afero.File, error) {
|
||||||
|
fBox, err := f.Box.Open(name)
|
||||||
|
if nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &file{f: fBox}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenFile is not supported for a RiceFs.
|
||||||
|
func (f *RiceFs) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) {
|
||||||
|
return nil, ErrUseOpen
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove is not supported for a RiceFs.
|
||||||
|
func (f *RiceFs) Remove(name string) error { return ErrReadOnly }
|
||||||
|
|
||||||
|
// RemoveAll is not supported for a RiceFs.
|
||||||
|
func (f *RiceFs) RemoveAll(path string) error { return ErrReadOnly }
|
||||||
|
|
||||||
|
// Rename is not supported for a RiceFs.
|
||||||
|
func (f *RiceFs) Rename(oldname, newname string) error { return ErrReadOnly }
|
||||||
|
|
||||||
|
// Stat returns a FileInfo describing the named file, or an error, if any happens.
|
||||||
|
func (f *RiceFs) Stat(name string) (os.FileInfo, error) {
|
||||||
|
fBox, err := f.Box.Open(name)
|
||||||
|
if nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return fBox.Stat()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the name of the file system
|
||||||
|
func (f *RiceFs) Name() string {
|
||||||
|
return "Rice FS"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chmod is not supported for a RiceFs.
|
||||||
|
func (f *RiceFs) Chmod(name string, mode os.FileMode) error { return ErrReadOnly }
|
||||||
|
|
||||||
|
// Chtimes is not supported for a RiceFs.
|
||||||
|
func (f *RiceFs) Chtimes(name string, atime time.Time, mtime time.Time) error { return ErrReadOnly }
|
71
vfs/copydir.go
Normal file
71
vfs/copydir.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package vfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/spf13/afero"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CopyDir interface {
|
||||||
|
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) 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)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user