Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 15fef29

Browse files
smolamcuadros
authored andcommitted
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.
1 parent 9abc801 commit 15fef29

File tree

3 files changed

+163
-52
lines changed

3 files changed

+163
-52
lines changed

utils/fs/fs.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@ var (
1414
)
1515

1616
type Filesystem interface {
17-
//Create opens a file in write-only mode.
1817
Create(filename string) (File, error)
19-
//Open opens a file in read-only mode.
2018
Open(filename string) (File, error)
19+
OpenFile(filename string, flag int, perm os.FileMode) (File, error)
2120
Stat(filename string) (FileInfo, error)
2221
ReadDir(path string) ([]FileInfo, error)
2322
TempFile(dir, prefix string) (File, error)
@@ -38,3 +37,16 @@ type File interface {
3837
}
3938

4039
type FileInfo os.FileInfo
40+
41+
type BaseFile struct {
42+
BaseFilename string
43+
Closed bool
44+
}
45+
46+
func (f *BaseFile) Filename() string {
47+
return f.BaseFilename
48+
}
49+
50+
func (f *BaseFile) IsClosed() bool {
51+
return f.Closed
52+
}

utils/fs/os/os.go

Lines changed: 29 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"path"
77
"path/filepath"
88

9-
. "gopkg.in/src-d/go-git.v4/utils/fs"
9+
"gopkg.in/src-d/go-git.v4/utils/fs"
1010
)
1111

1212
// OS a filesystem base on the os filesystem
@@ -21,15 +21,24 @@ func NewOS(baseDir string) *OS {
2121
}
2222
}
2323

24-
// Create creates a new GlusterFSFile
25-
func (fs *OS) Create(filename string) (File, error) {
24+
// Create creates a file and opens it with standard permissions
25+
// and modes O_RDWR, O_CREATE and O_TRUNC.
26+
func (fs *OS) Create(filename string) (fs.File, error) {
27+
return fs.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
28+
}
29+
30+
// OpenFile is equivalent to standard os.OpenFile.
31+
// If flag os.O_CREATE is set, all parent directories will be created.
32+
func (fs *OS) OpenFile(filename string, flag int, perm os.FileMode) (fs.File, error) {
2633
fullpath := path.Join(fs.base, filename)
2734

28-
if err := fs.createDir(fullpath); err != nil {
29-
return nil, err
35+
if flag|os.O_CREATE != 0 {
36+
if err := fs.createDir(fullpath); err != nil {
37+
return nil, err
38+
}
3039
}
3140

32-
f, err := os.Create(fullpath)
41+
f, err := os.OpenFile(fullpath, flag, perm)
3342
if err != nil {
3443
return nil, err
3544
}
@@ -55,15 +64,15 @@ func (fs *OS) createDir(fullpath string) error {
5564

5665
// ReadDir returns the filesystem info for all the archives under the specified
5766
// path.
58-
func (fs *OS) ReadDir(path string) ([]FileInfo, error) {
59-
fullpath := fs.Join(fs.base, path)
67+
func (ofs *OS) ReadDir(path string) ([]fs.FileInfo, error) {
68+
fullpath := ofs.Join(ofs.base, path)
6069

6170
l, err := ioutil.ReadDir(fullpath)
6271
if err != nil {
6372
return nil, err
6473
}
6574

66-
var s = make([]FileInfo, len(l))
75+
var s = make([]fs.FileInfo, len(l))
6776
for i, f := range l {
6877
s[i] = f
6978
}
@@ -82,20 +91,13 @@ func (fs *OS) Rename(from, to string) error {
8291
return os.Rename(from, to)
8392
}
8493

85-
// Open opens the named file for reading. If successful, methods on the returned
86-
// file can be used for reading only.
87-
func (fs *OS) Open(filename string) (File, error) {
88-
fullpath := fs.Join(fs.base, filename)
89-
f, err := os.Open(fullpath)
90-
if err != nil {
91-
return nil, err
92-
}
93-
94-
return newOSFile(filename, f), nil
94+
// Open opens a file in read-only mode.
95+
func (fs *OS) Open(filename string) (fs.File, error) {
96+
return fs.OpenFile(filename, os.O_RDONLY, 0)
9597
}
9698

9799
// Stat returns the FileInfo structure describing file.
98-
func (fs *OS) Stat(filename string) (FileInfo, error) {
100+
func (fs *OS) Stat(filename string) (fs.FileInfo, error) {
99101
fullpath := fs.Join(fs.base, filename)
100102
return os.Stat(fullpath)
101103
}
@@ -105,7 +107,7 @@ func (fs *OS) Remove(filename string) error {
105107
return os.Remove(fullpath)
106108
}
107109

108-
func (fs *OS) TempFile(dir, prefix string) (File, error) {
110+
func (fs *OS) TempFile(dir, prefix string) (fs.File, error) {
109111
fullpath := fs.Join(fs.base, dir)
110112
if err := fs.createDir(fullpath + string(os.PathSeparator)); err != nil {
111113
return nil, err
@@ -136,7 +138,7 @@ func (fs *OS) Join(elem ...string) string {
136138

137139
// Dir returns a new Filesystem from the same type of fs using as baseDir the
138140
// given path
139-
func (fs *OS) Dir(path string) Filesystem {
141+
func (fs *OS) Dir(path string) fs.Filesystem {
140142
return NewOS(fs.Join(fs.base, path))
141143
}
142144

@@ -147,15 +149,13 @@ func (fs *OS) Base() string {
147149

148150
// osFile represents a file in the os filesystem
149151
type osFile struct {
150-
filename string
151-
closed bool
152-
file *os.File
152+
fs.BaseFile
153+
file *os.File
153154
}
154155

155-
func newOSFile(filename string, file *os.File) File {
156+
func newOSFile(filename string, file *os.File) fs.File {
156157
return &osFile{
157-
filename: filename,
158-
closed: false,
158+
BaseFile: fs.BaseFile{BaseFilename: filename},
159159
file: file,
160160
}
161161
}
@@ -173,21 +173,11 @@ func (f *osFile) Write(p []byte) (int, error) {
173173
}
174174

175175
func (f *osFile) Close() error {
176-
f.closed = true
176+
f.BaseFile.Closed = true
177177

178178
return f.file.Close()
179179
}
180180

181181
func (f *osFile) ReadAt(p []byte, off int64) (n int, err error) {
182182
return f.file.ReadAt(p, off)
183183
}
184-
185-
//Filename returns the filename from the File
186-
func (f *osFile) Filename() string {
187-
return f.filename
188-
}
189-
190-
//IsClosed returns if te file is closed
191-
func (f *osFile) IsClosed() bool {
192-
return f.closed
193-
}

utils/fs/test/fs_suite.go

Lines changed: 120 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package test
33
import (
44
"fmt"
55
"io/ioutil"
6+
"os"
67
"strings"
78
"testing"
89

@@ -35,13 +36,13 @@ func (s *FilesystemSuite) TestCreateDepthAbsolute(c *C) {
3536
}
3637

3738
func (s *FilesystemSuite) TestCreateOverwrite(c *C) {
38-
for i := 0; i < 2; i++ {
39+
for i := 0; i < 3; i++ {
3940
f, err := s.Fs.Create("foo")
4041
c.Assert(err, IsNil)
4142

42-
l, err := f.Write([]byte("foo"))
43+
l, err := f.Write([]byte(fmt.Sprintf("foo%d", i)))
4344
c.Assert(err, IsNil)
44-
c.Assert(l, Equals, 3)
45+
c.Assert(l, Equals, 4)
4546

4647
err = f.Close()
4748
c.Assert(err, IsNil)
@@ -52,25 +53,135 @@ func (s *FilesystemSuite) TestCreateOverwrite(c *C) {
5253

5354
wrote, err := ioutil.ReadAll(f)
5455
c.Assert(err, IsNil)
55-
c.Assert(wrote, DeepEquals, []byte("foo"))
56+
c.Assert(string(wrote), DeepEquals, "foo2")
5657
}
5758

5859
func (s *FilesystemSuite) TestCreateClose(c *C) {
5960
f, err := s.Fs.Create("foo")
6061
c.Assert(err, IsNil)
6162
c.Assert(f.IsClosed(), Equals, false)
6263

63-
f.Write([]byte("foo"))
64+
_, err = f.Write([]byte("foo"))
65+
c.Assert(err, IsNil)
66+
c.Assert(f.Close(), IsNil)
67+
68+
f, err = s.Fs.Open(f.Filename())
69+
c.Assert(err, IsNil)
70+
71+
wrote, err := ioutil.ReadAll(f)
72+
c.Assert(err, IsNil)
73+
c.Assert(string(wrote), DeepEquals, "foo")
6474
c.Assert(f.Close(), IsNil)
75+
}
76+
77+
func (s *FilesystemSuite) TestOpenFileNoTruncate(c *C) {
78+
defaultMode := os.FileMode(0666)
79+
80+
// Create when it does not exist
81+
f, err := s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY, defaultMode)
82+
c.Assert(err, IsNil)
83+
c.Assert(f.Filename(), Equals, "foo1")
84+
s.testWriteClose(c, f, "foo1")
85+
86+
f, err = s.Fs.OpenFile("foo1", os.O_RDONLY, defaultMode)
87+
c.Assert(err, IsNil)
88+
s.testReadClose(c, f, "foo1")
89+
90+
// Create when it does exist
91+
f, err = s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY, defaultMode)
92+
c.Assert(err, IsNil)
93+
c.Assert(f.Filename(), Equals, "foo1")
94+
s.testWriteClose(c, f, "bar")
95+
96+
f, err = s.Fs.OpenFile("foo1", os.O_RDONLY, defaultMode)
97+
c.Assert(err, IsNil)
98+
s.testReadClose(c, f, "bar1")
99+
}
100+
101+
func (s *FilesystemSuite) TestOpenFileAppend(c *C) {
102+
defaultMode := os.FileMode(0666)
103+
104+
f, err := s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_APPEND, defaultMode)
105+
c.Assert(err, IsNil)
106+
c.Assert(f.Filename(), Equals, "foo1")
107+
s.testWriteClose(c, f, "foo1")
108+
109+
f, err = s.Fs.OpenFile("foo1", os.O_WRONLY|os.O_APPEND, defaultMode)
110+
c.Assert(err, IsNil)
111+
c.Assert(f.Filename(), Equals, "foo1")
112+
s.testWriteClose(c, f, "bar1")
113+
114+
f, err = s.Fs.OpenFile("foo1", os.O_RDONLY, defaultMode)
115+
c.Assert(err, IsNil)
116+
s.testReadClose(c, f, "foo1bar1")
117+
}
118+
119+
func (s *FilesystemSuite) TestOpenFileReadWrite(c *C) {
120+
defaultMode := os.FileMode(0666)
65121

66-
file, err := s.Fs.Open(f.Filename())
122+
f, err := s.Fs.OpenFile("foo1", os.O_CREATE|os.O_TRUNC|os.O_RDWR, defaultMode)
67123
c.Assert(err, IsNil)
124+
c.Assert(f.Filename(), Equals, "foo1")
68125

69-
wrote, err := ioutil.ReadAll(file)
126+
written, err := f.Write([]byte("foobar"))
127+
c.Assert(written, Equals, 6)
70128
c.Assert(err, IsNil)
71-
c.Assert(wrote, DeepEquals, []byte("foo"))
72129

73-
c.Assert(f.IsClosed(), Equals, true)
130+
_, err = f.Seek(0, os.SEEK_SET)
131+
c.Assert(err, IsNil)
132+
133+
written, err = f.Write([]byte("qux"))
134+
c.Assert(written, Equals, 3)
135+
c.Assert(err, IsNil)
136+
137+
_, err = f.Seek(0, os.SEEK_SET)
138+
c.Assert(err, IsNil)
139+
140+
s.testReadClose(c, f, "quxbar")
141+
}
142+
143+
func (s *FilesystemSuite) TestOpenFile(c *C) {
144+
defaultMode := os.FileMode(0666)
145+
146+
f, err := s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode)
147+
c.Assert(err, IsNil)
148+
s.testWriteClose(c, f, "foo1")
149+
150+
// Truncate if it exists
151+
f, err = s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode)
152+
c.Assert(err, IsNil)
153+
c.Assert(f.Filename(), Equals, "foo1")
154+
s.testWriteClose(c, f, "foo1overwritten")
155+
156+
// Read-only if it exists
157+
f, err = s.Fs.OpenFile("foo1", os.O_RDONLY, defaultMode)
158+
c.Assert(err, IsNil)
159+
c.Assert(f.Filename(), Equals, "foo1")
160+
s.testReadClose(c, f, "foo1overwritten")
161+
162+
// Create when it does exist
163+
f, err = s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode)
164+
c.Assert(err, IsNil)
165+
c.Assert(f.Filename(), Equals, "foo1")
166+
s.testWriteClose(c, f, "bar")
167+
168+
f, err = s.Fs.OpenFile("foo1", os.O_RDONLY, defaultMode)
169+
c.Assert(err, IsNil)
170+
s.testReadClose(c, f, "bar")
171+
}
172+
173+
func (s *FilesystemSuite) testWriteClose(c *C, f File, content string) {
174+
written, err := f.Write([]byte(content))
175+
c.Assert(written, Equals, len(content))
176+
c.Assert(err, IsNil)
177+
c.Assert(f.Close(), IsNil)
178+
}
179+
180+
func (s *FilesystemSuite) testReadClose(c *C, f File, content string) {
181+
read, err := ioutil.ReadAll(f)
182+
c.Assert(err, IsNil)
183+
c.Assert(string(read), Equals, content)
184+
c.Assert(f.Close(), IsNil)
74185
}
75186

76187
func (s *FilesystemSuite) TestReadDirAndDir(c *C) {
@@ -148,14 +259,12 @@ func (s *FilesystemSuite) TestTempFile(c *C) {
148259
func (s *FilesystemSuite) TestTempFileWithPath(c *C) {
149260
f, err := s.Fs.TempFile("foo", "bar")
150261
c.Assert(err, IsNil)
151-
fmt.Printf("f: %s\n", f.Filename())
152262
c.Assert(strings.HasPrefix(f.Filename(), s.Fs.Join("foo", "bar")), Equals, true)
153263
}
154264

155265
func (s *FilesystemSuite) TestTempFileFullWithPath(c *C) {
156266
f, err := s.Fs.TempFile("/foo", "bar")
157267
c.Assert(err, IsNil)
158-
fmt.Printf("f: %s\n", f.Filename())
159268
c.Assert(strings.HasPrefix(f.Filename(), s.Fs.Join("foo", "bar")), Equals, true)
160269
}
161270

0 commit comments

Comments
 (0)