107 lines
3.4 KiB
Go
107 lines
3.4 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}
|
||
|
}
|
||
|
|
||
|
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) })
|
||
|
}
|
||
|
|
||
|
// 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) })
|
||
|
}
|