2021-06-19 15:08:07 +03:00
|
|
|
package afero
|
|
|
|
|
|
|
|
import (
|
2022-07-15 15:25:51 +03:00
|
|
|
"io/fs"
|
2021-06-19 15:08:07 +03:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"syscall"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2022-01-10 19:06:32 +03:00
|
|
|
// FilePredicateFs filters files (not directories) by predicate,
|
2021-06-19 15:08:07 +03:00
|
|
|
// which takes file path as an arg.
|
2022-01-10 19:06:32 +03:00
|
|
|
type FilePredicateFs struct {
|
2021-06-19 15:08:07 +03:00
|
|
|
pred func(string) bool
|
|
|
|
source Fs
|
|
|
|
}
|
|
|
|
|
2022-07-15 15:25:51 +03:00
|
|
|
var (
|
|
|
|
_ fs.ReadDirFile = (*PredicateFile)(nil)
|
|
|
|
)
|
|
|
|
|
2022-01-10 19:06:32 +03:00
|
|
|
func NewFilePredicateFs(source Fs, pred func(string) bool) Fs {
|
|
|
|
return &FilePredicateFs{source: source, pred: pred}
|
2021-06-19 15:08:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
type PredicateFile struct {
|
|
|
|
f File
|
|
|
|
pred func(string) bool
|
|
|
|
}
|
|
|
|
|
2022-01-10 19:06:32 +03:00
|
|
|
func (p *FilePredicateFs) validate(path string) error {
|
2021-06-19 15:08:07 +03:00
|
|
|
if p.pred(path) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return syscall.ENOENT
|
|
|
|
}
|
|
|
|
|
2022-01-10 19:06:32 +03:00
|
|
|
func (p *FilePredicateFs) dirOrValidPath(path string) error {
|
2021-06-19 15:08:07 +03:00
|
|
|
dir, err := IsDir(p.source, path)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if dir {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return p.validate(path)
|
|
|
|
}
|
|
|
|
|
2022-01-10 19:06:32 +03:00
|
|
|
func (p *FilePredicateFs) Chtimes(path string, a, m time.Time) error {
|
2021-06-19 15:08:07 +03:00
|
|
|
if err := p.dirOrValidPath(path); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return p.source.Chtimes(path, a, m)
|
|
|
|
}
|
|
|
|
|
2022-01-10 19:06:32 +03:00
|
|
|
func (p *FilePredicateFs) Chmod(path string, mode os.FileMode) error {
|
2021-06-19 15:08:07 +03:00
|
|
|
if err := p.dirOrValidPath(path); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return p.source.Chmod(path, mode)
|
|
|
|
}
|
|
|
|
|
2022-01-10 19:06:32 +03:00
|
|
|
func (p *FilePredicateFs) Chown(path string, uid, gid int) error {
|
2021-06-19 15:08:07 +03:00
|
|
|
if err := p.dirOrValidPath(path); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return p.source.Chown(path, uid, gid)
|
|
|
|
}
|
|
|
|
|
2022-01-10 19:06:32 +03:00
|
|
|
func (p *FilePredicateFs) Name() string {
|
|
|
|
return "FilePredicateFs"
|
2021-06-19 15:08:07 +03:00
|
|
|
}
|
|
|
|
|
2022-01-10 19:06:32 +03:00
|
|
|
func (p *FilePredicateFs) Stat(path string) (os.FileInfo, error) {
|
2021-06-19 15:08:07 +03:00
|
|
|
if err := p.dirOrValidPath(path); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return p.source.Stat(path)
|
|
|
|
}
|
|
|
|
|
2022-01-10 19:06:32 +03:00
|
|
|
func (p *FilePredicateFs) Rename(oldname, newname string) error {
|
2021-06-19 15:08:07 +03:00
|
|
|
dir, err := IsDir(p.source, oldname)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if dir {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if err := p.validate(oldname); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := p.validate(newname); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return p.source.Rename(oldname, newname)
|
|
|
|
}
|
|
|
|
|
2022-01-10 19:06:32 +03:00
|
|
|
func (p *FilePredicateFs) RemoveAll(path string) error {
|
2021-06-19 15:08:07 +03:00
|
|
|
dir, err := IsDir(p.source, path)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if !dir {
|
|
|
|
if err := p.validate(path); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return p.source.RemoveAll(path)
|
|
|
|
}
|
|
|
|
|
2022-01-10 19:06:32 +03:00
|
|
|
func (p *FilePredicateFs) Remove(path string) error {
|
2021-06-19 15:08:07 +03:00
|
|
|
if err := p.dirOrValidPath(path); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return p.source.Remove(path)
|
|
|
|
}
|
|
|
|
|
2022-01-10 19:06:32 +03:00
|
|
|
func (p *FilePredicateFs) OpenFile(path string, flag int, perm os.FileMode) (File, error) {
|
2021-06-19 15:08:07 +03:00
|
|
|
if err := p.dirOrValidPath(path); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return p.source.OpenFile(path, flag, perm)
|
|
|
|
}
|
|
|
|
|
2022-01-10 19:06:32 +03:00
|
|
|
func (p *FilePredicateFs) Open(path string) (File, error) {
|
2021-06-19 15:08:07 +03:00
|
|
|
dir, err := IsDir(p.source, path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if !dir {
|
|
|
|
if err := p.validate(path); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f, err := p.source.Open(path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &PredicateFile{f: f, pred: p.pred}, nil
|
|
|
|
}
|
|
|
|
|
2022-01-10 19:06:32 +03:00
|
|
|
func (p *FilePredicateFs) Mkdir(n string, path os.FileMode) error {
|
2021-06-19 15:08:07 +03:00
|
|
|
return p.source.Mkdir(n, path)
|
|
|
|
}
|
|
|
|
|
2022-01-10 19:06:32 +03:00
|
|
|
func (p *FilePredicateFs) MkdirAll(n string, path os.FileMode) error {
|
2021-06-19 15:08:07 +03:00
|
|
|
return p.source.MkdirAll(n, path)
|
|
|
|
}
|
|
|
|
|
2022-01-10 19:06:32 +03:00
|
|
|
func (p *FilePredicateFs) Create(path string) (File, error) {
|
2021-06-19 15:08:07 +03:00
|
|
|
if err := p.validate(path); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return p.source.Create(path)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PredicateFile) Close() error {
|
|
|
|
return f.f.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PredicateFile) Read(s []byte) (int, error) {
|
|
|
|
return f.f.Read(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PredicateFile) ReadAt(s []byte, o int64) (int, error) {
|
|
|
|
return f.f.ReadAt(s, o)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PredicateFile) Seek(o int64, w int) (int64, error) {
|
|
|
|
return f.f.Seek(o, w)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PredicateFile) Write(s []byte) (int, error) {
|
|
|
|
return f.f.Write(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PredicateFile) WriteAt(s []byte, o int64) (int, error) {
|
|
|
|
return f.f.WriteAt(s, o)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PredicateFile) Name() string {
|
|
|
|
return f.f.Name()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PredicateFile) Readdir(c int) (fi []os.FileInfo, err error) {
|
|
|
|
var pfi []os.FileInfo
|
|
|
|
pfi, err = f.f.Readdir(c)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
for _, i := range pfi {
|
|
|
|
if i.IsDir() || f.pred(filepath.Join(f.f.Name(), i.Name())) {
|
|
|
|
fi = append(fi, i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return fi, nil
|
|
|
|
}
|
|
|
|
|
2022-07-15 15:25:51 +03:00
|
|
|
func (f *PredicateFile) ReadDir(n int) (filtered []fs.DirEntry, err error) {
|
|
|
|
var entreis []fs.DirEntry
|
|
|
|
if rdf, ok := f.f.(fs.ReadDirFile); ok {
|
|
|
|
entreis, err = rdf.ReadDir(n)
|
|
|
|
} else {
|
|
|
|
entreis, err = readDirFile{f.f}.ReadDir(n)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
for _, e := range entreis {
|
|
|
|
if e.IsDir() || f.pred(filepath.Join(f.f.Name(), e.Name())) {
|
|
|
|
filtered = append(filtered, e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return filtered, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-06-19 15:08:07 +03:00
|
|
|
func (f *PredicateFile) Readdirnames(c int) (n []string, err error) {
|
|
|
|
fi, err := f.Readdir(c)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
for _, s := range fi {
|
|
|
|
n = append(n, s.Name())
|
|
|
|
}
|
|
|
|
return n, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PredicateFile) Stat() (os.FileInfo, error) {
|
|
|
|
return f.f.Stat()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PredicateFile) Sync() error {
|
|
|
|
return f.f.Sync()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PredicateFile) Truncate(s int64) error {
|
|
|
|
return f.f.Truncate(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PredicateFile) WriteString(s string) (int, error) {
|
|
|
|
return f.f.WriteString(s)
|
|
|
|
}
|