port RO & Regexp from filter to filesystem

This commit is contained in:
Steve Francia 2016-01-11 15:31:07 -05:00
parent da00b1fb7c
commit 84018f2b47
5 changed files with 92 additions and 130 deletions

View File

@ -1,80 +0,0 @@
package afero
import (
"os"
"syscall"
"time"
)
type ReadOnlyFilter struct {
source Fs
}
func NewReadonlyFilter() FilterFs {
return &ReadOnlyFilter{}
}
func (r *ReadOnlyFilter) SetSource(fs Fs) {
r.source = fs
}
// prepend a filter in the filter chain
func (r *ReadOnlyFilter) AddFilter(fs FilterFs) {
fs.SetSource(r.source)
r.source = fs
}
func (r *ReadOnlyFilter) ReadDir(name string) ([]os.FileInfo, error) {
return ReadDir(r.source, name)
}
func (r *ReadOnlyFilter) Chtimes(n string, a, m time.Time) error {
return syscall.EPERM
}
func (r *ReadOnlyFilter) Chmod(n string, m os.FileMode) error {
return syscall.EPERM
}
func (r *ReadOnlyFilter) Name() string {
return "ReadOnlyFilter"
}
func (r *ReadOnlyFilter) Stat(name string) (os.FileInfo, error) {
return r.source.Stat(name)
}
func (r *ReadOnlyFilter) Rename(o, n string) error {
return syscall.EPERM
}
func (r *ReadOnlyFilter) RemoveAll(p string) error {
return syscall.EPERM
}
func (r *ReadOnlyFilter) Remove(n string) error {
return syscall.EPERM
}
func (r *ReadOnlyFilter) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
if flag&(os.O_WRONLY|syscall.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC) != 0 {
return nil, syscall.EPERM
}
return r.source.OpenFile(name, flag, perm)
}
func (r *ReadOnlyFilter) Open(n string) (File, error) {
return r.source.Open(n)
}
func (r *ReadOnlyFilter) Mkdir(n string, p os.FileMode) error {
return syscall.EPERM
}
func (r *ReadOnlyFilter) MkdirAll(n string, p os.FileMode) error {
return syscall.EPERM
}
func (r *ReadOnlyFilter) Create(n string) (File, error) {
return nil, syscall.EPERM
}

66
readonlyfs.go Normal file
View File

@ -0,0 +1,66 @@
package afero
import (
"os"
"syscall"
"time"
)
type ReadOnlyFs struct {
source Fs
}
func (r *ReadOnlyFs) ReadDir(name string) ([]os.FileInfo, error) {
return ReadDir(r.source, name)
}
func (r *ReadOnlyFs) Chtimes(n string, a, m time.Time) error {
return syscall.EPERM
}
func (r *ReadOnlyFs) Chmod(n string, m os.FileMode) error {
return syscall.EPERM
}
func (r *ReadOnlyFs) Name() string {
return "ReadOnlyFilter"
}
func (r *ReadOnlyFs) Stat(name string) (os.FileInfo, error) {
return r.source.Stat(name)
}
func (r *ReadOnlyFs) Rename(o, n string) error {
return syscall.EPERM
}
func (r *ReadOnlyFs) RemoveAll(p string) error {
return syscall.EPERM
}
func (r *ReadOnlyFs) Remove(n string) error {
return syscall.EPERM
}
func (r *ReadOnlyFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
if flag&(os.O_WRONLY|syscall.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC) != 0 {
return nil, syscall.EPERM
}
return r.source.OpenFile(name, flag, perm)
}
func (r *ReadOnlyFs) Open(n string) (File, error) {
return r.source.Open(n)
}
func (r *ReadOnlyFs) Mkdir(n string, p os.FileMode) error {
return syscall.EPERM
}
func (r *ReadOnlyFs) MkdirAll(n string, p os.FileMode) error {
return syscall.EPERM
}
func (r *ReadOnlyFs) Create(n string) (File, error) {
return nil, syscall.EPERM
}

View File

@ -7,11 +7,11 @@ import (
"time"
)
// The RegexpFilter filters files (not directories) by regular expression. Only
// The RegexpFs filters files (not directories) by regular expression. Only
// files matching the given regexp will be allowed, all others get a ENOENT error (
// "No such file or directory").
//
type RegexpFilter struct {
type RegexpFs struct {
re *regexp.Regexp
source Fs
}
@ -21,21 +21,7 @@ type RegexpFile struct {
re *regexp.Regexp
}
func NewRegexpFilter(re *regexp.Regexp) FilterFs {
return &RegexpFilter{re: re}
}
// prepend a filter in the filter chain
func (r *RegexpFilter) AddFilter(fs FilterFs) {
fs.SetSource(r.source)
r.source = fs
}
func (r *RegexpFilter) SetSource(fs Fs) {
r.source = fs
}
func (r *RegexpFilter) matchesName(name string) error {
func (r *RegexpFs) matchesName(name string) error {
if r.re == nil {
return nil
}
@ -45,7 +31,7 @@ func (r *RegexpFilter) matchesName(name string) error {
return syscall.ENOENT
}
func (r *RegexpFilter) dirOrMatches(name string) error {
func (r *RegexpFs) dirOrMatches(name string) error {
dir, err := IsDir(r.source, name)
if err != nil {
return err
@ -56,32 +42,32 @@ func (r *RegexpFilter) dirOrMatches(name string) error {
return r.matchesName(name)
}
func (r *RegexpFilter) Chtimes(name string, a, m time.Time) error {
func (r *RegexpFs) Chtimes(name string, a, m time.Time) error {
if err := r.dirOrMatches(name); err != nil {
return err
}
return r.source.Chtimes(name, a, m)
}
func (r *RegexpFilter) Chmod(name string, mode os.FileMode) error {
func (r *RegexpFs) Chmod(name string, mode os.FileMode) error {
if err := r.dirOrMatches(name); err != nil {
return err
}
return r.source.Chmod(name, mode)
}
func (r *RegexpFilter) Name() string {
return "RegexpFilter"
func (r *RegexpFs) Name() string {
return "RegexpFs"
}
func (r *RegexpFilter) Stat(name string) (os.FileInfo, error) {
func (r *RegexpFs) Stat(name string) (os.FileInfo, error) {
if err := r.dirOrMatches(name); err != nil {
return nil, err
}
return r.source.Stat(name)
}
func (r *RegexpFilter) Rename(oldname, newname string) error {
func (r *RegexpFs) Rename(oldname, newname string) error {
dir, err := IsDir(r.source, oldname)
if err != nil {
return err
@ -98,7 +84,7 @@ func (r *RegexpFilter) Rename(oldname, newname string) error {
return r.source.Rename(oldname, newname)
}
func (r *RegexpFilter) RemoveAll(p string) error {
func (r *RegexpFs) RemoveAll(p string) error {
dir, err := IsDir(r.source, p)
if err != nil {
return err
@ -111,21 +97,21 @@ func (r *RegexpFilter) RemoveAll(p string) error {
return r.source.RemoveAll(p)
}
func (r *RegexpFilter) Remove(name string) error {
func (r *RegexpFs) Remove(name string) error {
if err := r.dirOrMatches(name); err != nil {
return err
}
return r.source.Remove(name)
}
func (r *RegexpFilter) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
func (r *RegexpFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
if err := r.dirOrMatches(name); err != nil {
return nil, err
}
return r.source.OpenFile(name, flag, perm)
}
func (r *RegexpFilter) Open(name string) (File, error) {
func (r *RegexpFs) Open(name string) (File, error) {
dir, err := IsDir(r.source, name)
if err != nil {
return nil, err
@ -139,15 +125,15 @@ func (r *RegexpFilter) Open(name string) (File, error) {
return &RegexpFile{f: f, re: r.re}, nil
}
func (r *RegexpFilter) Mkdir(n string, p os.FileMode) error {
func (r *RegexpFs) Mkdir(n string, p os.FileMode) error {
return r.source.Mkdir(n, p)
}
func (r *RegexpFilter) MkdirAll(n string, p os.FileMode) error {
func (r *RegexpFs) MkdirAll(n string, p os.FileMode) error {
return r.source.MkdirAll(n, p)
}
func (r *RegexpFilter) Create(name string) (File, error) {
func (r *RegexpFs) Create(name string) (File, error) {
if err := r.matchesName(name); err != nil {
return nil, err
}

View File

@ -6,9 +6,7 @@ import (
)
func TestFilterReadOnly(t *testing.T) {
mfs := &MemMapFs{}
fs := NewFilter(mfs)
fs.AddFilter(NewReadonlyFilter())
fs := &ReadOnlyFs{source: &MemMapFs{}}
_, err := fs.Create("/file.txt")
if err == nil {
t.Errorf("Did not fail to create file")
@ -22,8 +20,7 @@ func TestFilterReadonlyRemoveAndRead(t *testing.T) {
fh.Write([]byte("content here"))
fh.Close()
fs := NewFilter(mfs)
fs.AddFilter(NewReadonlyFilter())
fs := &ReadOnlyFs{source: mfs}
err = fs.Remove("/file.txt")
if err == nil {
t.Errorf("Did not fail to remove file")
@ -54,9 +51,7 @@ func TestFilterReadonlyRemoveAndRead(t *testing.T) {
}
func TestFilterRegexp(t *testing.T) {
mfs := &MemMapFs{}
fs := NewFilter(mfs)
fs.AddFilter(NewRegexpFilter(regexp.MustCompile(`\.txt$`)))
fs := &RegexpFs{re: regexp.MustCompile(`\.txt$`), source: &MemMapFs{}}
_, err := fs.Create("/file.html")
if err == nil {
@ -66,10 +61,8 @@ func TestFilterRegexp(t *testing.T) {
}
func TestFilterRORegexpChain(t *testing.T) {
mfs := &MemMapFs{}
fs := NewFilter(mfs)
fs.AddFilter(NewReadonlyFilter())
fs.AddFilter(NewRegexpFilter(regexp.MustCompile(`\.txt$`)))
rofs := &ReadOnlyFs{source: &MemMapFs{}}
fs := &RegexpFs{re: regexp.MustCompile(`\.txt$`), source: rofs}
_, err := fs.Create("/file.txt")
if err == nil {
t.Errorf("Did not fail to create file")
@ -79,9 +72,8 @@ func TestFilterRORegexpChain(t *testing.T) {
func TestFilterRegexReadDir(t *testing.T) {
mfs := &MemMapFs{}
fs := NewFilter(mfs)
fs.AddFilter(NewRegexpFilter(regexp.MustCompile(`\.txt$`)))
fs.AddFilter(NewRegexpFilter(regexp.MustCompile(`^a`)))
fs1 := &RegexpFs{re: regexp.MustCompile(`\.txt$`), source: mfs}
fs := &RegexpFs{re: regexp.MustCompile(`^a`), source: fs1}
mfs.MkdirAll("/dir/sub", 0777)
for _, name := range []string{"afile.txt", "afile.html", "bfile.txt"} {

View File

@ -9,8 +9,7 @@ import (
func TestUnionCreateExisting(t *testing.T) {
base := &MemMapFs{}
roBase := NewFilter(base)
roBase.AddFilter(NewReadonlyFilter())
roBase := &ReadOnlyFs{source: base}
ufs := NewUnionFs(roBase, &MemMapFs{}, NewCoWUnionFs())
@ -60,8 +59,7 @@ func TestUnionCreateExisting(t *testing.T) {
func TestUnionMergeReaddir(t *testing.T) {
base := &MemMapFs{}
roBase := NewFilter(base)
roBase.AddFilter(NewReadonlyFilter())
roBase := &ReadOnlyFs{source: base}
ufs := NewUnionFs(roBase, &MemMapFs{}, NewCoWUnionFs())