diff options
author | Santiago M. Mola <santi@mola.io> | 2016-10-31 16:11:07 +0100 |
---|---|---|
committer | Máximo Cuadros <mcuadros@gmail.com> | 2016-10-31 15:11:07 +0000 |
commit | 5078f52a9f2217027b0f475d5a91e677b3228588 (patch) | |
tree | ad42e162e131456052938d77977c1030281126b9 | |
parent | 659386309f36c482ddc0bb9e854ebda3da216491 (diff) | |
download | go-git-5078f52a9f2217027b0f475d5a91e677b3228588.tar.gz |
utils/fs: add OpenFile method to filesystem interface. (#104)
* utils/fs: add OpenFile method to filesystem interface.
* added OpenFile to fs.Filesystem interface.
* added OpenFile implementation to 'os' filesystem.
* bring back BaseFile.
* utils/fs/os: do not use wildcard import.
* utils/fs/os: implement Open and Create using OpenFile.
-rw-r--r-- | utils/fs/fs.go | 16 | ||||
-rw-r--r-- | utils/fs/os/os.go | 68 | ||||
-rw-r--r-- | utils/fs/test/fs_suite.go | 131 |
3 files changed, 163 insertions, 52 deletions
diff --git a/utils/fs/fs.go b/utils/fs/fs.go index 463425c..7e6c01f 100644 --- a/utils/fs/fs.go +++ b/utils/fs/fs.go @@ -14,10 +14,9 @@ var ( ) type Filesystem interface { - //Create opens a file in write-only mode. Create(filename string) (File, error) - //Open opens a file in read-only mode. 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) @@ -38,3 +37,16 @@ type File interface { } 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/os/os.go b/utils/fs/os/os.go index 800bd41..02395d6 100644 --- a/utils/fs/os/os.go +++ b/utils/fs/os/os.go @@ -6,7 +6,7 @@ import ( "path" "path/filepath" - . "gopkg.in/src-d/go-git.v4/utils/fs" + "gopkg.in/src-d/go-git.v4/utils/fs" ) // OS a filesystem base on the os filesystem @@ -21,15 +21,24 @@ func NewOS(baseDir string) *OS { } } -// Create creates a new GlusterFSFile -func (fs *OS) Create(filename string) (File, error) { +// 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 err := fs.createDir(fullpath); err != nil { - return nil, err + if flag|os.O_CREATE != 0 { + if err := fs.createDir(fullpath); err != nil { + return nil, err + } } - f, err := os.Create(fullpath) + f, err := os.OpenFile(fullpath, flag, perm) if err != nil { return nil, err } @@ -55,15 +64,15 @@ func (fs *OS) createDir(fullpath string) error { // ReadDir returns the filesystem info for all the archives under the specified // path. -func (fs *OS) ReadDir(path string) ([]FileInfo, error) { - fullpath := fs.Join(fs.base, 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([]FileInfo, len(l)) + var s = make([]fs.FileInfo, len(l)) for i, f := range l { s[i] = f } @@ -82,20 +91,13 @@ func (fs *OS) Rename(from, to string) error { return os.Rename(from, to) } -// Open opens the named file for reading. If successful, methods on the returned -// file can be used for reading only. -func (fs *OS) Open(filename string) (File, error) { - fullpath := fs.Join(fs.base, filename) - f, err := os.Open(fullpath) - if err != nil { - return nil, err - } - - return newOSFile(filename, f), nil +// 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) (FileInfo, error) { +func (fs *OS) Stat(filename string) (fs.FileInfo, error) { fullpath := fs.Join(fs.base, filename) return os.Stat(fullpath) } @@ -105,7 +107,7 @@ func (fs *OS) Remove(filename string) error { return os.Remove(fullpath) } -func (fs *OS) TempFile(dir, prefix string) (File, error) { +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 @@ -136,7 +138,7 @@ func (fs *OS) Join(elem ...string) string { // Dir returns a new Filesystem from the same type of fs using as baseDir the // given path -func (fs *OS) Dir(path string) Filesystem { +func (fs *OS) Dir(path string) fs.Filesystem { return NewOS(fs.Join(fs.base, path)) } @@ -147,15 +149,13 @@ func (fs *OS) Base() string { // osFile represents a file in the os filesystem type osFile struct { - filename string - closed bool - file *os.File + fs.BaseFile + file *os.File } -func newOSFile(filename string, file *os.File) File { +func newOSFile(filename string, file *os.File) fs.File { return &osFile{ - filename: filename, - closed: false, + BaseFile: fs.BaseFile{BaseFilename: filename}, file: file, } } @@ -173,7 +173,7 @@ func (f *osFile) Write(p []byte) (int, error) { } func (f *osFile) Close() error { - f.closed = true + f.BaseFile.Closed = true return f.file.Close() } @@ -181,13 +181,3 @@ func (f *osFile) Close() error { func (f *osFile) ReadAt(p []byte, off int64) (n int, err error) { return f.file.ReadAt(p, off) } - -//Filename returns the filename from the File -func (f *osFile) Filename() string { - return f.filename -} - -//IsClosed returns if te file is closed -func (f *osFile) IsClosed() bool { - return f.closed -} diff --git a/utils/fs/test/fs_suite.go b/utils/fs/test/fs_suite.go index a809309..4c0fd09 100644 --- a/utils/fs/test/fs_suite.go +++ b/utils/fs/test/fs_suite.go @@ -3,6 +3,7 @@ package test import ( "fmt" "io/ioutil" + "os" "strings" "testing" @@ -35,13 +36,13 @@ func (s *FilesystemSuite) TestCreateDepthAbsolute(c *C) { } func (s *FilesystemSuite) TestCreateOverwrite(c *C) { - for i := 0; i < 2; i++ { + for i := 0; i < 3; i++ { f, err := s.Fs.Create("foo") c.Assert(err, IsNil) - l, err := f.Write([]byte("foo")) + l, err := f.Write([]byte(fmt.Sprintf("foo%d", i))) c.Assert(err, IsNil) - c.Assert(l, Equals, 3) + c.Assert(l, Equals, 4) err = f.Close() c.Assert(err, IsNil) @@ -52,7 +53,7 @@ func (s *FilesystemSuite) TestCreateOverwrite(c *C) { wrote, err := ioutil.ReadAll(f) c.Assert(err, IsNil) - c.Assert(wrote, DeepEquals, []byte("foo")) + c.Assert(string(wrote), DeepEquals, "foo2") } func (s *FilesystemSuite) TestCreateClose(c *C) { @@ -60,17 +61,127 @@ func (s *FilesystemSuite) TestCreateClose(c *C) { c.Assert(err, IsNil) c.Assert(f.IsClosed(), Equals, false) - f.Write([]byte("foo")) + _, 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) - file, err := s.Fs.Open(f.Filename()) + 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") - wrote, err := ioutil.ReadAll(file) + written, err := f.Write([]byte("foobar")) + c.Assert(written, Equals, 6) c.Assert(err, IsNil) - c.Assert(wrote, DeepEquals, []byte("foo")) - c.Assert(f.IsClosed(), Equals, true) + _, 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) TestReadDirAndDir(c *C) { @@ -148,14 +259,12 @@ func (s *FilesystemSuite) TestTempFile(c *C) { func (s *FilesystemSuite) TestTempFileWithPath(c *C) { f, err := s.Fs.TempFile("foo", "bar") c.Assert(err, IsNil) - fmt.Printf("f: %s\n", f.Filename()) 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) - fmt.Printf("f: %s\n", f.Filename()) c.Assert(strings.HasPrefix(f.Filename(), s.Fs.Join("foo", "bar")), Equals, true) } |