118 lines
3.9 KiB
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) })
|
|
}
|