fs/vfs/fallbackfs.go

118 lines
3.9 KiB
Go

package vfs
import (
"os"
"time"
"github.com/spf13/afero"
)
var _ afero.Fs = &FallbackFs{}
// FallbackFs presents a source Fs that falls back to a backup Fs when the Fs call fails.
type FallbackFs struct {
source afero.Fs
backup afero.Fs
}
// NewFallbackFs creates a new FallbackFs
func NewFallbackFs(source, backup afero.Fs) *FallbackFs {
return &FallbackFs{source, backup}
}
// NewOsFsFallback creates a new Fs based on the os package, restricts access on the supplied path and uses backup as fallback.
func NewOsFsFallback(path string, backup afero.Fs) *FallbackFs {
osFs := afero.NewOsFs()
return NewFallbackFs(afero.NewBasePathFs(osFs, path), backup)
}
func (f *FallbackFs) do(action func(afero.Fs) error) error {
err := action(f.source)
if err == nil {
return nil
}
return action(f.backup)
}
func (f *FallbackFs) doFile(action func(afero.Fs) (afero.File, error)) (afero.File, error) {
file, err := action(f.source)
if err == nil {
return file.(afero.File), nil
}
return action(f.backup)
}
func (f *FallbackFs) doFileInfo(action func(afero.Fs) (os.FileInfo, error)) (os.FileInfo, error) {
res, err := action(f.source)
if err == nil {
return res, nil
}
return action(f.backup)
}
// Create creates a file in the filesystem, returning the file and an error, if any happens.
func (f *FallbackFs) Create(name string) (afero.File, error) {
return f.doFile(func(fs afero.Fs) (afero.File, error) { return fs.Create(name) })
}
// Mkdir creates a directory in the filesystem, return an error if any happens.
func (f *FallbackFs) Mkdir(name string, perm os.FileMode) error {
return f.do(func(fs afero.Fs) error { return fs.Mkdir(name, perm) })
}
// MkdirAll creates a directory path and all parents that does not exist yet.
func (f *FallbackFs) MkdirAll(path string, perm os.FileMode) error {
return f.do(func(fs afero.Fs) error { return fs.MkdirAll(path, perm) })
}
// Open opens a file, returning it or an error, if any happens.
func (f *FallbackFs) Open(name string) (afero.File, error) {
return f.doFile(func(fs afero.Fs) (afero.File, error) { return fs.Open(name) })
}
// OpenFile opens a file using the given flags and the given mode.
func (f *FallbackFs) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) {
return f.doFile(func(fs afero.Fs) (afero.File, error) { return fs.OpenFile(name, flag, perm) })
}
// Remove removes a file identified by name, returning an error, if any happens.
func (f *FallbackFs) Remove(name string) error {
return f.do(func(fs afero.Fs) error { return fs.Remove(name) })
}
// RemoveAll removes a directory path and any children it contains. It does not fail if the path does not exist (return nil).
func (f *FallbackFs) RemoveAll(path string) error {
return f.do(func(fs afero.Fs) error { return fs.RemoveAll(path) })
}
// Rename renames a file.
func (f *FallbackFs) Rename(oldname, newname string) error {
return f.do(func(fs afero.Fs) error { return fs.Rename(oldname, newname) })
}
// Stat returns a FileInfo describing the named file, or an error, if any happens.
func (f *FallbackFs) Stat(name string) (os.FileInfo, error) {
return f.doFileInfo(func(fs afero.Fs) (os.FileInfo, error) { return fs.Stat(name) })
}
// Name returns the name of the file system.
func (f *FallbackFs) Name() string {
return "Fallback FS"
}
// Chmod changes the mode of the named file to mode.
func (f *FallbackFs) Chmod(name string, mode os.FileMode) error {
return f.do(func(fs afero.Fs) error { return fs.Chmod(name, mode) })
}
// Chown changes the uid and gid of the named file.
func (f *FallbackFs) Chown(name string, uid, gid int) error {
return f.do(func(fs afero.Fs) error { return fs.Chown(name, uid, gid) })
}
// Chtimes changes the access and modification times of the named file.
func (f *FallbackFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
return f.do(func(fs afero.Fs) error { return fs.Chtimes(name, atime, mtime) })
}