forked from mirror/afero
Make OsFs.Open interoperable with others (with tests confirming)
This commit is contained in:
parent
969a70f798
commit
2ec8b79d61
|
@ -1,15 +1,52 @@
|
||||||
package afero
|
package afero
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
"fmt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var tempDirs []string
|
var tempDirs []string
|
||||||
|
|
||||||
|
func NewTempOsBaseFs(t *testing.T) Fs {
|
||||||
|
name, err := TempDir(NewOsFs(), "", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Error("error creating tempDir", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tempDirs = append(tempDirs, name)
|
||||||
|
|
||||||
|
return NewBasePathFs(NewOsFs(), name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CleanupTempDirs(t *testing.T) {
|
||||||
|
osfs := NewOsFs()
|
||||||
|
type ev struct{
|
||||||
|
path string
|
||||||
|
e error
|
||||||
|
}
|
||||||
|
|
||||||
|
errs := []ev{}
|
||||||
|
|
||||||
|
for _, x := range tempDirs {
|
||||||
|
err := osfs.RemoveAll(x)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, ev{path:x,e: err})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, e := range errs {
|
||||||
|
fmt.Println("error removing tempDir", e.path, e.e)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(errs) > 0 {
|
||||||
|
t.Error("error cleaning up tempDirs")
|
||||||
|
}
|
||||||
|
tempDirs = []string{}
|
||||||
|
}
|
||||||
|
|
||||||
func TestUnionCreateExisting(t *testing.T) {
|
func TestUnionCreateExisting(t *testing.T) {
|
||||||
base := &MemMapFs{}
|
base := &MemMapFs{}
|
||||||
roBase := &ReadOnlyFs{source: base}
|
roBase := &ReadOnlyFs{source: base}
|
||||||
|
@ -125,31 +162,110 @@ func TestExistingDirectoryCollisionReaddir(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTempOsBaseFs(t *testing.T) Fs {
|
func TestNestedDirBaseReaddir(t *testing.T) {
|
||||||
name, err := TempDir(NewOsFs(), "", "")
|
base := &MemMapFs{}
|
||||||
|
roBase := &ReadOnlyFs{source: base}
|
||||||
|
overlay := &MemMapFs{}
|
||||||
|
|
||||||
|
ufs := &CopyOnWriteFs{base: roBase, layer: overlay}
|
||||||
|
|
||||||
|
base.MkdirAll("/home/test/foo/bar", 0777)
|
||||||
|
fh, _ := base.Create("/home/test/file.txt")
|
||||||
|
fh.WriteString("This is a test")
|
||||||
|
fh.Close()
|
||||||
|
|
||||||
|
fh, _ = base.Create("/home/test/foo/file2.txt")
|
||||||
|
fh.WriteString("This is a test")
|
||||||
|
fh.Close()
|
||||||
|
fh, _ = base.Create("/home/test/foo/bar/file3.txt")
|
||||||
|
fh.WriteString("This is a test")
|
||||||
|
fh.Close()
|
||||||
|
|
||||||
|
overlay.MkdirAll("/", 0777)
|
||||||
|
|
||||||
|
// Opening something only in the base
|
||||||
|
fh, _ = ufs.Open("/home/test/foo")
|
||||||
|
list, err := fh.Readdir(-1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("error creating tempDir", err)
|
t.Errorf("Readdir failed", err)
|
||||||
|
}
|
||||||
|
if len(list) != 2 {
|
||||||
|
for _, x := range list {
|
||||||
|
fmt.Println(x.Name())
|
||||||
|
}
|
||||||
|
t.Errorf("Got wrong number of files in union: %v", len(list))
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("created tempdir", name)
|
|
||||||
tempDirs = append(tempDirs, name)
|
|
||||||
|
|
||||||
return NewBasePathFs(NewOsFs(), name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func CleanupTempDirs() {
|
func TestNestedDirOverlayReaddir(t *testing.T) {
|
||||||
osfs := NewOsFs()
|
base := &MemMapFs{}
|
||||||
for _, x := range tempDirs {
|
roBase := &ReadOnlyFs{source: base}
|
||||||
err := osfs.RemoveAll(x)
|
overlay := &MemMapFs{}
|
||||||
|
|
||||||
|
ufs := &CopyOnWriteFs{base: roBase, layer: overlay}
|
||||||
|
|
||||||
|
base.MkdirAll("/", 0777)
|
||||||
|
overlay.MkdirAll("/home/test/foo/bar", 0777)
|
||||||
|
fh, _ := overlay.Create("/home/test/file.txt")
|
||||||
|
fh.WriteString("This is a test")
|
||||||
|
fh.Close()
|
||||||
|
fh, _ = overlay.Create("/home/test/foo/file2.txt")
|
||||||
|
fh.WriteString("This is a test")
|
||||||
|
fh.Close()
|
||||||
|
fh, _ = overlay.Create("/home/test/foo/bar/file3.txt")
|
||||||
|
fh.WriteString("This is a test")
|
||||||
|
fh.Close()
|
||||||
|
|
||||||
|
// Opening nested dir only in the overlay
|
||||||
|
fh, _ = ufs.Open("/home/test/foo")
|
||||||
|
list, err := fh.Readdir(-1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("error removing tempDir", x, err)
|
t.Errorf("Readdir failed", err)
|
||||||
}
|
}
|
||||||
|
if len(list) != 2 {
|
||||||
|
for _, x := range list {
|
||||||
|
fmt.Println(x.Name())
|
||||||
|
}
|
||||||
|
t.Errorf("Got wrong number of files in union: %v", len(list))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNestedDirOverlayOsFsReaddir(t *testing.T) {
|
||||||
|
defer CleanupTempDirs(t)
|
||||||
|
base := NewTempOsBaseFs(t)
|
||||||
|
roBase := &ReadOnlyFs{source: base}
|
||||||
|
overlay := NewTempOsBaseFs(t)
|
||||||
|
|
||||||
|
ufs := &CopyOnWriteFs{base: roBase, layer: overlay}
|
||||||
|
|
||||||
|
base.MkdirAll("/", 0777)
|
||||||
|
overlay.MkdirAll("/home/test/foo/bar", 0777)
|
||||||
|
fh, _ := overlay.Create("/home/test/file.txt")
|
||||||
|
fh.WriteString("This is a test")
|
||||||
|
fh.Close()
|
||||||
|
fh, _ = overlay.Create("/home/test/foo/file2.txt")
|
||||||
|
fh.WriteString("This is a test")
|
||||||
|
fh.Close()
|
||||||
|
fh, _ = overlay.Create("/home/test/foo/bar/file3.txt")
|
||||||
|
fh.WriteString("This is a test")
|
||||||
|
fh.Close()
|
||||||
|
|
||||||
|
// Opening nested dir only in the overlay
|
||||||
|
fh, _ = ufs.Open("/home/test/foo")
|
||||||
|
list, err := fh.Readdir(-1)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Readdir failed", err)
|
||||||
|
}
|
||||||
|
if len(list) != 2 {
|
||||||
|
for _, x := range list {
|
||||||
|
fmt.Println(x.Name())
|
||||||
|
}
|
||||||
|
t.Errorf("Got wrong number of files in union: %v", len(list))
|
||||||
}
|
}
|
||||||
tempDirs = []string{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCopyOnWriteFsWithOsFs(t *testing.T) {
|
func TestCopyOnWriteFsWithOsFs(t *testing.T) {
|
||||||
defer CleanupTempDirs()
|
defer CleanupTempDirs(t)
|
||||||
base := NewTempOsBaseFs(t)
|
base := NewTempOsBaseFs(t)
|
||||||
roBase := &ReadOnlyFs{source: base}
|
roBase := &ReadOnlyFs{source: base}
|
||||||
overlay := NewTempOsBaseFs(t)
|
overlay := NewTempOsBaseFs(t)
|
||||||
|
|
|
@ -26,6 +26,8 @@ func NewCopyOnWriteFs(base Fs, layer Fs) Fs {
|
||||||
return &CopyOnWriteFs{base: base, layer: layer}
|
return &CopyOnWriteFs{base: base, layer: layer}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isBaseFile Returns true if the given file is only found in the base layer
|
||||||
|
// will return true if file is not found in either layer
|
||||||
func (u *CopyOnWriteFs) isBaseFile(name string) (bool, error) {
|
func (u *CopyOnWriteFs) isBaseFile(name string) (bool, error) {
|
||||||
if _, err := u.layer.Stat(name); err == nil {
|
if _, err := u.layer.Stat(name); err == nil {
|
||||||
return false, nil
|
return false, nil
|
||||||
|
@ -144,7 +146,9 @@ func (u *CopyOnWriteFs) Open(name string) (File, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if b {
|
if b {
|
||||||
|
// If it's only in the base (not overlay) return that File
|
||||||
return u.base.Open(name)
|
return u.base.Open(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,6 +157,7 @@ func (u *CopyOnWriteFs) Open(name string) (File, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !dir {
|
if !dir {
|
||||||
|
// If it's in the overlay and not a directory, return that file
|
||||||
return u.layer.Open(name)
|
return u.layer.Open(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +166,7 @@ func (u *CopyOnWriteFs) Open(name string) (File, error) {
|
||||||
if err != nil && bfile == nil {
|
if err != nil && bfile == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// If it's a directory in both, return a unionFile
|
||||||
return &UnionFile{base: bfile, layer: lfile}, nil
|
return &UnionFile{base: bfile, layer: lfile}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
19
os.go
19
os.go
|
@ -32,7 +32,11 @@ func NewOsFs() Fs {
|
||||||
func (OsFs) Name() string { return "OsFs" }
|
func (OsFs) Name() string { return "OsFs" }
|
||||||
|
|
||||||
func (OsFs) Create(name string) (File, error) {
|
func (OsFs) Create(name string) (File, error) {
|
||||||
return os.Create(name)
|
f, e := os.Create(name)
|
||||||
|
if f == nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
return f, e
|
||||||
}
|
}
|
||||||
|
|
||||||
func (OsFs) Mkdir(name string, perm os.FileMode) error {
|
func (OsFs) Mkdir(name string, perm os.FileMode) error {
|
||||||
|
@ -44,11 +48,20 @@ func (OsFs) MkdirAll(path string, perm os.FileMode) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (OsFs) Open(name string) (File, error) {
|
func (OsFs) Open(name string) (File, error) {
|
||||||
return os.Open(name)
|
f, e := os.Open(name)
|
||||||
|
|
||||||
|
if f == nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
return f, e
|
||||||
}
|
}
|
||||||
|
|
||||||
func (OsFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
|
func (OsFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
|
||||||
return os.OpenFile(name, flag, perm)
|
f, e := os.OpenFile(name, flag, perm)
|
||||||
|
if f == nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
return f, e
|
||||||
}
|
}
|
||||||
|
|
||||||
func (OsFs) Remove(name string) error {
|
func (OsFs) Remove(name string) error {
|
||||||
|
|
|
@ -123,6 +123,8 @@ func (f *UnionFile) Name() string {
|
||||||
return f.base.Name()
|
return f.base.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Readdir will weave the two directories together and
|
||||||
|
// return a single view of the overlayed directories
|
||||||
func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) {
|
func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) {
|
||||||
if f.off == 0 {
|
if f.off == 0 {
|
||||||
var files = make(map[string]os.FileInfo)
|
var files = make(map[string]os.FileInfo)
|
||||||
|
@ -136,6 +138,7 @@ func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) {
|
||||||
files[fi.Name()] = fi
|
files[fi.Name()] = fi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.base != nil {
|
if f.base != nil {
|
||||||
rfi, err = f.base.Readdir(-1)
|
rfi, err = f.base.Readdir(-1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue