From 1eb39394cdf09b26eb2f5c98225fb2912980e61f Mon Sep 17 00:00:00 2001 From: Sergio Arbeo Date: Mon, 19 Dec 2016 10:42:14 +0100 Subject: Extract billy (#173) * Extract billy Billy is a new library directly extracted from go-git. It abstract several storages systems in a filesystem interface. More in github.com/src-d/billy * Fix grouping in imports block * Update billy to v1 * Re-remove fs_implementation example --- utils/fs/fs.go | 52 ----- utils/fs/memory/memory.go | 364 ------------------------------- utils/fs/memory/memory_test.go | 33 --- utils/fs/os/os.go | 183 ---------------- utils/fs/os/os_test.go | 37 ---- utils/fs/test/fs_suite.go | 479 ----------------------------------------- 6 files changed, 1148 deletions(-) delete mode 100644 utils/fs/fs.go delete mode 100644 utils/fs/memory/memory.go delete mode 100644 utils/fs/memory/memory_test.go delete mode 100644 utils/fs/os/os.go delete mode 100644 utils/fs/os/os_test.go delete mode 100644 utils/fs/test/fs_suite.go (limited to 'utils/fs') diff --git a/utils/fs/fs.go b/utils/fs/fs.go deleted file mode 100644 index 7e6c01f..0000000 --- a/utils/fs/fs.go +++ /dev/null @@ -1,52 +0,0 @@ -// Package fs interace and implementations used by storage/filesystem -package fs - -import ( - "errors" - "io" - "os" -) - -var ( - ErrClosed = errors.New("file: Writing on closed file.") - ErrReadOnly = errors.New("this is a read-only filesystem") - ErrNotSupported = errors.New("feature not supported") -) - -type Filesystem interface { - Create(filename string) (File, error) - Open(filename string) (File, error) - OpenFile(filename string, flag int, perm os.FileMode) (File, error) - Stat(filename string) (FileInfo, error) - ReadDir(path string) ([]FileInfo, error) - TempFile(dir, prefix string) (File, error) - Rename(from, to string) error - Remove(filename string) error - Join(elem ...string) string - Dir(path string) Filesystem - Base() string -} - -type File interface { - Filename() string - IsClosed() bool - io.Writer - io.Reader - io.Seeker - io.Closer -} - -type FileInfo os.FileInfo - -type BaseFile struct { - BaseFilename string - Closed bool -} - -func (f *BaseFile) Filename() string { - return f.BaseFilename -} - -func (f *BaseFile) IsClosed() bool { - return f.Closed -} diff --git a/utils/fs/memory/memory.go b/utils/fs/memory/memory.go deleted file mode 100644 index 54dd497..0000000 --- a/utils/fs/memory/memory.go +++ /dev/null @@ -1,364 +0,0 @@ -package memory - -import ( - "errors" - "fmt" - "io" - "os" - "path/filepath" - "strings" - "time" - - "gopkg.in/src-d/go-git.v4/utils/fs" -) - -const separator = '/' - -// Memory a very convenient filesystem based on memory files -type Memory struct { - base string - s *storage - tempCount int -} - -//New returns a new Memory filesystem -func New() *Memory { - return &Memory{ - base: "/", - s: &storage{make(map[string]*file, 0)}, - } -} - -func (fs *Memory) Create(filename string) (fs.File, error) { - return fs.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0) -} - -func (fs *Memory) Open(filename string) (fs.File, error) { - return fs.OpenFile(filename, os.O_RDONLY, 0) -} - -func (fs *Memory) OpenFile(filename string, flag int, perm os.FileMode) (fs.File, error) { - fullpath := fs.Join(fs.base, filename) - f, ok := fs.s.files[fullpath] - - if !ok && !isCreate(flag) { - return nil, os.ErrNotExist - } - - if f == nil { - fs.s.files[fullpath] = newFile(fs.base, fullpath, flag) - return fs.s.files[fullpath], nil - } - - n := newFile(fs.base, fullpath, flag) - n.content = f.content - - if isAppend(flag) { - n.position = int64(n.content.Len()) - } - - if isTruncate(flag) { - n.content.Truncate() - } - - return n, nil -} - -func (fs *Memory) Stat(filename string) (fs.FileInfo, error) { - fullpath := fs.Join(fs.base, filename) - - if _, ok := fs.s.files[filename]; ok { - return newFileInfo(fs.base, fullpath, fs.s.files[filename].content.Len()), nil - } - - info, err := fs.ReadDir(filename) - if err == nil && len(info) != 0 { - return newFileInfo(fs.base, fullpath, len(info)), nil - } - - return nil, os.ErrNotExist -} - -func (fs *Memory) ReadDir(base string) (entries []fs.FileInfo, err error) { - base = fs.Join(fs.base, base) - - appendedDirs := make(map[string]bool, 0) - for fullpath, f := range fs.s.files { - if !strings.HasPrefix(fullpath, base) { - continue - } - - fullpath, _ = filepath.Rel(base, fullpath) - parts := strings.Split(fullpath, string(separator)) - - if len(parts) == 1 { - entries = append(entries, &fileInfo{name: parts[0], size: f.content.Len()}) - continue - } - - if _, ok := appendedDirs[parts[0]]; ok { - continue - } - - entries = append(entries, &fileInfo{name: parts[0], isDir: true}) - appendedDirs[parts[0]] = true - } - - return -} - -var maxTempFiles = 1024 * 4 - -func (fs *Memory) TempFile(dir, prefix string) (fs.File, error) { - var fullpath string - for { - if fs.tempCount >= maxTempFiles { - return nil, errors.New("max. number of tempfiles reached") - } - - fullpath = fs.getTempFilename(dir, prefix) - if _, ok := fs.s.files[fullpath]; !ok { - break - } - } - - return fs.Create(fullpath) -} - -func (fs *Memory) getTempFilename(dir, prefix string) string { - fs.tempCount++ - filename := fmt.Sprintf("%s_%d_%d", prefix, fs.tempCount, time.Now().UnixNano()) - return fs.Join(fs.base, dir, filename) -} - -func (fs *Memory) Rename(from, to string) error { - from = fs.Join(fs.base, from) - to = fs.Join(fs.base, to) - - if _, ok := fs.s.files[from]; !ok { - return os.ErrNotExist - } - - fs.s.files[to] = fs.s.files[from] - fs.s.files[to].BaseFilename = to - delete(fs.s.files, from) - - return nil -} - -func (fs *Memory) Remove(filename string) error { - fullpath := fs.Join(fs.base, filename) - if _, ok := fs.s.files[fullpath]; !ok { - return os.ErrNotExist - } - - delete(fs.s.files, fullpath) - return nil -} - -func (fs *Memory) Join(elem ...string) string { - return filepath.Join(elem...) -} - -func (fs *Memory) Dir(path string) fs.Filesystem { - return &Memory{ - base: fs.Join(fs.base, path), - s: fs.s, - } -} - -func (fs *Memory) Base() string { - return fs.base -} - -type file struct { - fs.BaseFile - - content *content - position int64 - flag int -} - -func newFile(base, fullpath string, flag int) *file { - filename, _ := filepath.Rel(base, fullpath) - - return &file{ - BaseFile: fs.BaseFile{BaseFilename: filename}, - content: &content{}, - flag: flag, - } -} - -func (f *file) Read(b []byte) (int, error) { - n, err := f.ReadAt(b, f.position) - if err != nil { - return 0, err - } - - return n, err -} - -func (f *file) ReadAt(b []byte, off int64) (int, error) { - if f.IsClosed() { - return 0, fs.ErrClosed - } - - if !isReadAndWrite(f.flag) && !isReadOnly(f.flag) { - return 0, errors.New("read not supported") - } - - n, err := f.content.ReadAt(b, off) - f.position += int64(n) - - return n, err -} - -func (f *file) Seek(offset int64, whence int) (int64, error) { - if f.IsClosed() { - return 0, fs.ErrClosed - } - - switch whence { - case io.SeekCurrent: - f.position += offset - case io.SeekStart: - f.position = offset - case io.SeekEnd: - f.position = int64(f.content.Len()) - offset - } - - return f.position, nil -} - -func (f *file) Write(p []byte) (int, error) { - if f.IsClosed() { - return 0, fs.ErrClosed - } - - if !isReadAndWrite(f.flag) && !isWriteOnly(f.flag) { - return 0, errors.New("write not supported") - } - - n, err := f.content.WriteAt(p, f.position) - f.position += int64(n) - - return n, err -} - -func (f *file) Close() error { - if f.IsClosed() { - return errors.New("file already closed") - } - - f.Closed = true - return nil -} - -func (f *file) Open() error { - f.Closed = false - return nil -} - -type fileInfo struct { - name string - size int - isDir bool -} - -func newFileInfo(base, fullpath string, size int) *fileInfo { - filename, _ := filepath.Rel(base, fullpath) - - return &fileInfo{ - name: filename, - size: size, - } -} - -func (fi *fileInfo) Name() string { - return fi.name -} - -func (fi *fileInfo) Size() int64 { - return int64(fi.size) -} - -func (fi *fileInfo) Mode() os.FileMode { - return os.FileMode(0) -} - -func (*fileInfo) ModTime() time.Time { - return time.Now() -} - -func (fi *fileInfo) IsDir() bool { - return fi.isDir -} - -func (*fileInfo) Sys() interface{} { - return nil -} - -type storage struct { - files map[string]*file -} - -type content struct { - bytes []byte -} - -func (c *content) WriteAt(p []byte, off int64) (int, error) { - prev := len(c.bytes) - c.bytes = append(c.bytes[:off], p...) - if len(c.bytes) < prev { - c.bytes = c.bytes[:prev] - } - - return len(p), nil -} - -func (c *content) ReadAt(b []byte, off int64) (int, error) { - size := int64(len(c.bytes)) - if off >= size { - return 0, io.EOF - } - - l := int64(len(b)) - if off+l > size { - l = size - off - } - - n := copy(b, c.bytes[off:off+l]) - return n, nil -} - -func (c *content) Truncate() { - c.bytes = make([]byte, 0) -} - -func (c *content) Len() int { - return len(c.bytes) -} - -func isCreate(flag int) bool { - return flag&os.O_CREATE != 0 -} - -func isAppend(flag int) bool { - return flag&os.O_APPEND != 0 -} - -func isTruncate(flag int) bool { - return flag&os.O_TRUNC != 0 -} - -func isReadAndWrite(flag int) bool { - return flag&os.O_RDWR != 0 -} - -func isReadOnly(flag int) bool { - return flag == os.O_RDONLY -} - -func isWriteOnly(flag int) bool { - return flag&os.O_WRONLY != 0 -} diff --git a/utils/fs/memory/memory_test.go b/utils/fs/memory/memory_test.go deleted file mode 100644 index 4645fe7..0000000 --- a/utils/fs/memory/memory_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package memory - -import ( - "testing" - - . "gopkg.in/check.v1" - "gopkg.in/src-d/go-git.v4/utils/fs/test" -) - -func Test(t *testing.T) { TestingT(t) } - -type MemorySuite struct { - test.FilesystemSuite - path string -} - -var _ = Suite(&MemorySuite{}) - -func (s *MemorySuite) SetUpTest(c *C) { - s.FilesystemSuite.Fs = New() -} - -func (s *MemorySuite) TestTempFileMaxTempFiles(c *C) { - for i := 0; i < maxTempFiles; i++ { - f, err := s.FilesystemSuite.Fs.TempFile("", "") - c.Assert(err, IsNil) - c.Assert(f, NotNil) - } - - f, err := s.FilesystemSuite.Fs.TempFile("", "") - c.Assert(err, NotNil) - c.Assert(f, IsNil) -} diff --git a/utils/fs/os/os.go b/utils/fs/os/os.go deleted file mode 100644 index 5f9df67..0000000 --- a/utils/fs/os/os.go +++ /dev/null @@ -1,183 +0,0 @@ -package os - -import ( - "io/ioutil" - "os" - "path" - "path/filepath" - - "gopkg.in/src-d/go-git.v4/utils/fs" -) - -// OS a filesystem base on the os filesystem -type OS struct { - base string -} - -// New returns a new OS filesystem -func New(baseDir string) *OS { - return &OS{ - base: baseDir, - } -} - -// Create creates a file and opens it with standard permissions -// and modes O_RDWR, O_CREATE and O_TRUNC. -func (fs *OS) Create(filename string) (fs.File, error) { - return fs.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) -} - -// OpenFile is equivalent to standard os.OpenFile. -// If flag os.O_CREATE is set, all parent directories will be created. -func (fs *OS) OpenFile(filename string, flag int, perm os.FileMode) (fs.File, error) { - fullpath := path.Join(fs.base, filename) - - if flag&os.O_CREATE != 0 { - if err := fs.createDir(fullpath); err != nil { - return nil, err - } - } - - f, err := os.OpenFile(fullpath, flag, perm) - if err != nil { - return nil, err - } - - filename, err = filepath.Rel(fs.base, fullpath) - if err != nil { - return nil, err - } - - return newOSFile(filename, f), nil -} - -func (fs *OS) createDir(fullpath string) error { - dir := filepath.Dir(fullpath) - if dir != "." { - if err := os.MkdirAll(dir, 0755); err != nil { - return err - } - } - - return nil -} - -// ReadDir returns the filesystem info for all the archives under the specified -// path. -func (ofs *OS) ReadDir(path string) ([]fs.FileInfo, error) { - fullpath := ofs.Join(ofs.base, path) - - l, err := ioutil.ReadDir(fullpath) - if err != nil { - return nil, err - } - - var s = make([]fs.FileInfo, len(l)) - for i, f := range l { - s[i] = f - } - - return s, nil -} - -func (fs *OS) Rename(from, to string) error { - from = fs.Join(fs.base, from) - to = fs.Join(fs.base, to) - - if err := fs.createDir(to); err != nil { - return err - } - - return os.Rename(from, to) -} - -// Open opens a file in read-only mode. -func (fs *OS) Open(filename string) (fs.File, error) { - return fs.OpenFile(filename, os.O_RDONLY, 0) -} - -// Stat returns the FileInfo structure describing file. -func (fs *OS) Stat(filename string) (fs.FileInfo, error) { - fullpath := fs.Join(fs.base, filename) - return os.Stat(fullpath) -} - -func (fs *OS) Remove(filename string) error { - fullpath := fs.Join(fs.base, filename) - return os.Remove(fullpath) -} - -func (fs *OS) TempFile(dir, prefix string) (fs.File, error) { - fullpath := fs.Join(fs.base, dir) - if err := fs.createDir(fullpath + string(os.PathSeparator)); err != nil { - return nil, err - } - - f, err := ioutil.TempFile(fullpath, prefix) - if err != nil { - return nil, err - } - - s, err := f.Stat() - if err != nil { - return nil, err - } - - filename, err := filepath.Rel(fs.base, fs.Join(fullpath, s.Name())) - if err != nil { - return nil, err - } - - return newOSFile(filename, f), nil -} - -// Join joins the specified elements using the filesystem separator. -func (fs *OS) Join(elem ...string) string { - return filepath.Join(elem...) -} - -// Dir returns a new Filesystem from the same type of fs using as baseDir the -// given path -func (fs *OS) Dir(path string) fs.Filesystem { - return New(fs.Join(fs.base, path)) -} - -// Base returns the base path of the filesytem -func (fs *OS) Base() string { - return fs.base -} - -// osFile represents a file in the os filesystem -type osFile struct { - fs.BaseFile - file *os.File -} - -func newOSFile(filename string, file *os.File) fs.File { - return &osFile{ - BaseFile: fs.BaseFile{BaseFilename: filename}, - file: file, - } -} - -func (f *osFile) Read(p []byte) (int, error) { - return f.file.Read(p) -} - -func (f *osFile) Seek(offset int64, whence int) (int64, error) { - return f.file.Seek(offset, whence) -} - -func (f *osFile) Write(p []byte) (int, error) { - return f.file.Write(p) -} - -func (f *osFile) Close() error { - f.BaseFile.Closed = true - - return f.file.Close() -} - -func (f *osFile) ReadAt(p []byte, off int64) (int, error) { - return f.file.ReadAt(p, off) -} diff --git a/utils/fs/os/os_test.go b/utils/fs/os/os_test.go deleted file mode 100644 index 5e8f5c1..0000000 --- a/utils/fs/os/os_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package os_test - -import ( - "io/ioutil" - stdos "os" - "path/filepath" - "testing" - - . "gopkg.in/check.v1" - "gopkg.in/src-d/go-git.v4/utils/fs/os" - "gopkg.in/src-d/go-git.v4/utils/fs/test" -) - -func Test(t *testing.T) { TestingT(t) } - -type OSSuite struct { - test.FilesystemSuite - path string -} - -var _ = Suite(&OSSuite{}) - -func (s *OSSuite) SetUpTest(c *C) { - s.path, _ = ioutil.TempDir(stdos.TempDir(), "go-git-os-fs-test") - s.FilesystemSuite.Fs = os.New(s.path) -} -func (s *OSSuite) TearDownTest(c *C) { - err := stdos.RemoveAll(s.path) - c.Assert(err, IsNil) -} - -func (s *OSSuite) TestOpenDoesNotCreateDir(c *C) { - _, err := s.Fs.Open("dir/non-existent") - c.Assert(err, NotNil) - _, err = stdos.Stat(filepath.Join(s.path, "dir")) - c.Assert(stdos.IsNotExist(err), Equals, true) -} diff --git a/utils/fs/test/fs_suite.go b/utils/fs/test/fs_suite.go deleted file mode 100644 index 91b2be5..0000000 --- a/utils/fs/test/fs_suite.go +++ /dev/null @@ -1,479 +0,0 @@ -package test - -import ( - "fmt" - "io" - "io/ioutil" - "os" - "strings" - "testing" - - "bytes" - - . "gopkg.in/check.v1" - . "gopkg.in/src-d/go-git.v4/utils/fs" -) - -func Test(t *testing.T) { TestingT(t) } - -type FilesystemSuite struct { - Fs Filesystem -} - -func (s *FilesystemSuite) TestCreate(c *C) { - f, err := s.Fs.Create("foo") - c.Assert(err, IsNil) - c.Assert(f.Filename(), Equals, "foo") -} - -func (s *FilesystemSuite) TestCreateDepth(c *C) { - f, err := s.Fs.Create("bar/foo") - c.Assert(err, IsNil) - c.Assert(f.Filename(), Equals, "bar/foo") -} - -func (s *FilesystemSuite) TestCreateDepthAbsolute(c *C) { - f, err := s.Fs.Create("/bar/foo") - c.Assert(err, IsNil) - c.Assert(f.Filename(), Equals, "bar/foo") -} - -func (s *FilesystemSuite) TestCreateOverwrite(c *C) { - for i := 0; i < 3; i++ { - f, err := s.Fs.Create("foo") - c.Assert(err, IsNil) - - l, err := f.Write([]byte(fmt.Sprintf("foo%d", i))) - c.Assert(err, IsNil) - c.Assert(l, Equals, 4) - - err = f.Close() - c.Assert(err, IsNil) - } - - f, err := s.Fs.Open("foo") - c.Assert(err, IsNil) - - wrote, err := ioutil.ReadAll(f) - c.Assert(err, IsNil) - c.Assert(string(wrote), DeepEquals, "foo2") -} - -func (s *FilesystemSuite) TestCreateClose(c *C) { - f, err := s.Fs.Create("foo") - c.Assert(err, IsNil) - c.Assert(f.IsClosed(), Equals, false) - - _, err = f.Write([]byte("foo")) - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - f, err = s.Fs.Open(f.Filename()) - c.Assert(err, IsNil) - - wrote, err := ioutil.ReadAll(f) - c.Assert(err, IsNil) - c.Assert(string(wrote), DeepEquals, "foo") - c.Assert(f.Close(), IsNil) -} - -func (s *FilesystemSuite) TestOpenFileNoTruncate(c *C) { - defaultMode := os.FileMode(0666) - - // Create when it does not exist - f, err := s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY, defaultMode) - c.Assert(err, IsNil) - c.Assert(f.Filename(), Equals, "foo1") - s.testWriteClose(c, f, "foo1") - - f, err = s.Fs.OpenFile("foo1", os.O_RDONLY, defaultMode) - c.Assert(err, IsNil) - s.testReadClose(c, f, "foo1") - - // Create when it does exist - f, err = s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY, defaultMode) - c.Assert(err, IsNil) - c.Assert(f.Filename(), Equals, "foo1") - s.testWriteClose(c, f, "bar") - - f, err = s.Fs.OpenFile("foo1", os.O_RDONLY, defaultMode) - c.Assert(err, IsNil) - s.testReadClose(c, f, "bar1") -} - -func (s *FilesystemSuite) TestOpenFileAppend(c *C) { - defaultMode := os.FileMode(0666) - - f, err := s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_APPEND, defaultMode) - c.Assert(err, IsNil) - c.Assert(f.Filename(), Equals, "foo1") - s.testWriteClose(c, f, "foo1") - - f, err = s.Fs.OpenFile("foo1", os.O_WRONLY|os.O_APPEND, defaultMode) - c.Assert(err, IsNil) - c.Assert(f.Filename(), Equals, "foo1") - s.testWriteClose(c, f, "bar1") - - f, err = s.Fs.OpenFile("foo1", os.O_RDONLY, defaultMode) - c.Assert(err, IsNil) - s.testReadClose(c, f, "foo1bar1") -} - -func (s *FilesystemSuite) TestOpenFileReadWrite(c *C) { - defaultMode := os.FileMode(0666) - - f, err := s.Fs.OpenFile("foo1", os.O_CREATE|os.O_TRUNC|os.O_RDWR, defaultMode) - c.Assert(err, IsNil) - c.Assert(f.Filename(), Equals, "foo1") - - written, err := f.Write([]byte("foobar")) - c.Assert(written, Equals, 6) - c.Assert(err, IsNil) - - _, err = f.Seek(0, os.SEEK_SET) - c.Assert(err, IsNil) - - written, err = f.Write([]byte("qux")) - c.Assert(written, Equals, 3) - c.Assert(err, IsNil) - - _, err = f.Seek(0, os.SEEK_SET) - c.Assert(err, IsNil) - - s.testReadClose(c, f, "quxbar") -} - -func (s *FilesystemSuite) TestOpenFile(c *C) { - defaultMode := os.FileMode(0666) - - f, err := s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode) - c.Assert(err, IsNil) - s.testWriteClose(c, f, "foo1") - - // Truncate if it exists - f, err = s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode) - c.Assert(err, IsNil) - c.Assert(f.Filename(), Equals, "foo1") - s.testWriteClose(c, f, "foo1overwritten") - - // Read-only if it exists - f, err = s.Fs.OpenFile("foo1", os.O_RDONLY, defaultMode) - c.Assert(err, IsNil) - c.Assert(f.Filename(), Equals, "foo1") - s.testReadClose(c, f, "foo1overwritten") - - // Create when it does exist - f, err = s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode) - c.Assert(err, IsNil) - c.Assert(f.Filename(), Equals, "foo1") - s.testWriteClose(c, f, "bar") - - f, err = s.Fs.OpenFile("foo1", os.O_RDONLY, defaultMode) - c.Assert(err, IsNil) - s.testReadClose(c, f, "bar") -} - -func (s *FilesystemSuite) testWriteClose(c *C, f File, content string) { - written, err := f.Write([]byte(content)) - c.Assert(written, Equals, len(content)) - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) -} - -func (s *FilesystemSuite) testReadClose(c *C, f File, content string) { - read, err := ioutil.ReadAll(f) - c.Assert(err, IsNil) - c.Assert(string(read), Equals, content) - c.Assert(f.Close(), IsNil) -} - -func (s *FilesystemSuite) TestFileCreateReadSeek(c *C) { - f, err := s.Fs.Create("foo") - c.Assert(err, IsNil) - - n, err := f.Write([]byte("0123456789abcdefghijklmnopqrstuvwxyz")) - c.Assert(err, IsNil) - c.Assert(n, Equals, 36) - - p, err := f.Seek(10, io.SeekStart) - c.Assert(err, IsNil) - c.Assert(int(p), Equals, 10) - - all, err := ioutil.ReadAll(f) - c.Assert(err, IsNil) - c.Assert(string(all), Equals, "abcdefghijklmnopqrstuvwxyz") - c.Assert(f.Close(), IsNil) -} - -func (s *FilesystemSuite) TestFileOpenReadSeek(c *C) { - f, err := s.Fs.Create("foo") - c.Assert(err, IsNil) - - n, err := f.Write([]byte("0123456789abcdefghijklmnopqrstuvwxyz")) - c.Assert(err, IsNil) - c.Assert(n, Equals, 36) - - c.Assert(f.Close(), IsNil) - - f, err = s.Fs.Open("foo") - c.Assert(err, IsNil) - - p, err := f.Seek(10, io.SeekStart) - c.Assert(err, IsNil) - c.Assert(int(p), Equals, 10) - - all, err := ioutil.ReadAll(f) - c.Assert(err, IsNil) - c.Assert(string(all), Equals, "abcdefghijklmnopqrstuvwxyz") - c.Assert(f.Close(), IsNil) -} - -func (s *FilesystemSuite) TestFileCloseTwice(c *C) { - f, err := s.Fs.Create("foo") - c.Assert(err, IsNil) - - c.Assert(f.Close(), IsNil) - c.Assert(f.Close(), NotNil) -} - -func (s *FilesystemSuite) TestReadDirAndDir(c *C) { - files := []string{"foo", "bar", "qux/baz", "qux/qux"} - for _, name := range files { - f, err := s.Fs.Create(name) - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - } - - info, err := s.Fs.ReadDir("/") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 3) - - info, err = s.Fs.ReadDir("/qux") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 2) - - qux := s.Fs.Dir("/qux") - info, err = qux.ReadDir("/") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 2) -} - -func (s *FilesystemSuite) TestReadDirFileInfo(c *C) { - f, err := s.Fs.Create("foo") - c.Assert(err, IsNil) - n, err := f.Write([]byte{'F', 'O', 'O'}) - c.Assert(n, Equals, 3) - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - info, err := s.Fs.ReadDir("/") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 1) - - c.Assert(info[0].Size(), Equals, int64(3)) - c.Assert(info[0].IsDir(), Equals, false) - c.Assert(info[0].Name(), Equals, "foo") -} - -func (s *FilesystemSuite) TestReadDirFileInfoDirs(c *C) { - files := []string{"qux/baz/foo"} - for _, name := range files { - f, err := s.Fs.Create(name) - c.Assert(err, IsNil) - n, err := f.Write([]byte{'F', 'O', 'O'}) - c.Assert(n, Equals, 3) - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - } - - info, err := s.Fs.ReadDir("qux") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 1) - c.Assert(info[0].IsDir(), Equals, true) - c.Assert(info[0].Name(), Equals, "baz") - - info, err = s.Fs.ReadDir("qux/baz") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 1) - c.Assert(info[0].Size(), Equals, int64(3)) - c.Assert(info[0].IsDir(), Equals, false) - c.Assert(info[0].Name(), Equals, "foo") -} - -func (s *FilesystemSuite) TestDirStat(c *C) { - files := []string{"foo", "bar", "qux/baz", "qux/qux"} - for _, name := range files { - f, err := s.Fs.Create(name) - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - } - - qux := s.Fs.Dir("qux") - fi, err := qux.Stat("baz") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "baz") - - fi, err = qux.Stat("/baz") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "baz") -} - -func (s *FilesystemSuite) TestCreateInDir(c *C) { - dir := s.Fs.Dir("foo") - f, err := dir.Create("bar") - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - c.Assert(f.Filename(), Equals, "bar") -} - -func (s *FilesystemSuite) TestRename(c *C) { - f, err := s.Fs.Create("foo") - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - err = s.Fs.Rename("foo", "bar") - c.Assert(err, IsNil) - - foo, err := s.Fs.Stat("foo") - c.Assert(foo, IsNil) - c.Assert(err, NotNil) - - bar, err := s.Fs.Stat("bar") - c.Assert(bar, NotNil) - c.Assert(err, IsNil) -} - -func (s *FilesystemSuite) TestTempFile(c *C) { - f, err := s.Fs.TempFile("", "bar") - c.Assert(err, IsNil) - - c.Assert(strings.HasPrefix(f.Filename(), "bar"), Equals, true) -} - -func (s *FilesystemSuite) TestTempFileWithPath(c *C) { - f, err := s.Fs.TempFile("foo", "bar") - c.Assert(err, IsNil) - c.Assert(strings.HasPrefix(f.Filename(), s.Fs.Join("foo", "bar")), Equals, true) -} - -func (s *FilesystemSuite) TestTempFileFullWithPath(c *C) { - f, err := s.Fs.TempFile("/foo", "bar") - c.Assert(err, IsNil) - c.Assert(strings.HasPrefix(f.Filename(), s.Fs.Join("foo", "bar")), Equals, true) -} - -func (s *FilesystemSuite) TestOpenAndWrite(c *C) { - f, err := s.Fs.Create("foo") - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - foo, err := s.Fs.Open("foo") - c.Assert(foo, NotNil) - c.Assert(err, IsNil) - - n, err := foo.Write([]byte("foo")) - c.Assert(err, NotNil) - c.Assert(n, Equals, 0) -} - -func (s *FilesystemSuite) TestOpenAndStat(c *C) { - f, err := s.Fs.Create("foo") - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - foo, err := s.Fs.Open("foo") - c.Assert(foo, NotNil) - c.Assert(foo.Filename(), Equals, "foo") - c.Assert(err, IsNil) - - stat, err := s.Fs.Stat("foo") - c.Assert(stat, NotNil) - c.Assert(err, IsNil) - c.Assert(stat.Name(), Equals, "foo") -} - -func (s *FilesystemSuite) TestRemove(c *C) { - f, err := s.Fs.Create("foo") - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - err = s.Fs.Remove("foo") - c.Assert(err, IsNil) -} - -func (s *FilesystemSuite) TestRemoveNonExisting(c *C) { - c.Assert(s.Fs.Remove("NON-EXISTING"), NotNil) -} - -func (s *FilesystemSuite) TestRemoveTempFile(c *C) { - f, err := s.Fs.TempFile("test-dir", "test-prefix") - c.Assert(err, IsNil) - - fn := f.Filename() - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - c.Assert(s.Fs.Remove(fn), IsNil) -} - -func (s *FilesystemSuite) TestJoin(c *C) { - c.Assert(s.Fs.Join("foo", "bar"), Equals, "foo/bar") -} - -func (s *FilesystemSuite) TestBase(c *C) { - c.Assert(s.Fs.Base(), Not(Equals), "") -} - -func (s *FilesystemSuite) TestReadAtOnReadWrite(c *C) { - f, err := s.Fs.Create("foo") - c.Assert(err, IsNil) - _, err = f.Write([]byte("abcdefg")) - c.Assert(err, IsNil) - rf, ok := f.(io.ReaderAt) - c.Assert(ok, Equals, true) - b := make([]byte, 3) - n, err := rf.ReadAt(b, 2) - c.Assert(err, IsNil) - c.Assert(n, Equals, 3) - c.Assert(string(b), Equals, "cde") - c.Assert(f.Close(), IsNil) -} - -func (s *FilesystemSuite) TestReadAtOnReadOnly(c *C) { - f, err := s.Fs.Create("foo") - c.Assert(err, IsNil) - _, err = f.Write([]byte("abcdefg")) - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - f, err = s.Fs.Open("foo") - c.Assert(err, IsNil) - rf, ok := f.(io.ReaderAt) - c.Assert(ok, Equals, true) - b := make([]byte, 3) - n, err := rf.ReadAt(b, 2) - c.Assert(err, IsNil) - c.Assert(n, Equals, 3) - c.Assert(string(b), Equals, "cde") - c.Assert(f.Close(), IsNil) -} - -func (s *FilesystemSuite) TestReadWriteLargeFile(c *C) { - f, err := s.Fs.Create("foo") - c.Assert(err, IsNil) - - size := 1 << 20 - - n, err := f.Write(bytes.Repeat([]byte("F"), size)) - c.Assert(err, IsNil) - c.Assert(n, Equals, size) - - err = f.Close() - c.Assert(err, IsNil) - - f, err = s.Fs.Open("foo") - c.Assert(err, IsNil) - b, err := ioutil.ReadAll(f) - c.Assert(err, IsNil) - c.Assert(len(b), Equals, size) -} -- cgit