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

Commit 490027a

Browse files
committed
utils: fs new implementation
1 parent 1ae588f commit 490027a

File tree

3 files changed

+178
-149
lines changed

3 files changed

+178
-149
lines changed

utils/fs/fs.go

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,49 @@
22
package fs
33

44
import (
5+
"errors"
56
"io"
67
"os"
78
)
89

9-
// FS interface represent an abstracted filesystem, so you can
10-
// use NewRepositoryFromFS from any medium.
11-
type FS interface {
12-
Stat(path string) (os.FileInfo, error)
13-
Open(path string) (ReadSeekCloser, error)
14-
ReadDir(path string) ([]os.FileInfo, error)
10+
var (
11+
ErrClosed = errors.New("File: Writing on closed file.")
12+
ErrReadOnly = errors.New("this is a read-only filesystem")
13+
ErrNotSupported = errors.New("feature not supported")
14+
)
15+
16+
type Filesystem interface {
17+
Create(filename string) (File, error)
18+
Open(filename string) (File, error)
19+
Rename(from, to string) error
20+
Stat(filename string) (FileInfo, error)
21+
ReadDir(path string) ([]FileInfo, error)
1522
Join(elem ...string) string
23+
Dir(path string) Filesystem
24+
Base() string
1625
}
1726

18-
// ReadSeekCloser is a Reader, Seeker and Closer.
19-
type ReadSeekCloser interface {
20-
io.ReadCloser
27+
type File interface {
28+
Filename() string
29+
io.Writer
30+
io.Reader
2131
io.Seeker
32+
io.Closer
33+
}
34+
35+
type FileInfo os.FileInfo
36+
37+
type BaseFile struct {
38+
filename string
39+
closed bool
40+
}
41+
42+
//Filename returns the filename from the File
43+
func (f *BaseFile) Filename() string {
44+
return f.filename
45+
}
46+
47+
//IsClosed returns if te file is closed
48+
func (f *BaseFile) IsClosed() bool {
49+
return f.closed
2250
}

utils/fs/os.go

Lines changed: 112 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,130 @@ package fs
33
import (
44
"io/ioutil"
55
"os"
6+
"path"
67
"path/filepath"
78
)
89

9-
// OS is a simple FS implementation for the current host filesystem.
10-
type OS struct{}
11-
1210
// NewOS returns a new OS.
13-
func NewOS() FS {
14-
return &OS{}
11+
func NewOS() Filesystem {
12+
return &OSClient{}
13+
}
14+
15+
// OSClient a filesystem based on OSClient
16+
type OSClient struct {
17+
RootDir string
18+
}
19+
20+
// NewOSClient returns a new OSClient
21+
func NewOSClient(rootDir string) *OSClient {
22+
return &OSClient{
23+
RootDir: rootDir,
24+
}
1525
}
1626

17-
// Stat returns the filesystem info for a path.
18-
func (o *OS) Stat(path string) (os.FileInfo, error) {
19-
return os.Stat(path)
27+
// Create creates a new GlusterFSFile
28+
func (c *OSClient) Create(filename string) (File, error) {
29+
fullpath := path.Join(c.RootDir, filename)
30+
31+
dir := filepath.Dir(fullpath)
32+
if dir != "." {
33+
if err := os.MkdirAll(dir, 0755); err != nil {
34+
return nil, err
35+
}
36+
}
37+
38+
f, err := os.Create(fullpath)
39+
if err != nil {
40+
return nil, err
41+
}
42+
43+
return &OSFile{
44+
BaseFile: BaseFile{filename: fullpath},
45+
file: f,
46+
}, nil
47+
}
48+
49+
// ReadDir returns the filesystem info for all the archives under the specified
50+
// path.
51+
func (c *OSClient) ReadDir(path string) ([]FileInfo, error) {
52+
fullpath := c.Join(c.RootDir, path)
53+
54+
l, err := ioutil.ReadDir(fullpath)
55+
if err != nil {
56+
return nil, err
57+
}
58+
59+
var s = make([]FileInfo, len(l))
60+
for i, f := range l {
61+
s[i] = f
62+
}
63+
64+
return s, nil
65+
}
66+
67+
func (c *OSClient) Rename(from, to string) error {
68+
if !filepath.IsAbs(from) {
69+
from = c.Join(c.RootDir, from)
70+
}
71+
72+
if !filepath.IsAbs(to) {
73+
to = c.Join(c.RootDir, to)
74+
}
75+
76+
return os.Rename(from, to)
2077
}
2178

22-
// Open returns a ReadSeekCloser for the specified path.
23-
func (o *OS) Open(path string) (ReadSeekCloser, error) {
24-
return os.Open(path)
79+
func (c *OSClient) Open(filename string) (File, error) {
80+
fullpath := c.Join(c.RootDir, filename)
81+
82+
f, err := os.Open(fullpath)
83+
if err != nil {
84+
return nil, err
85+
}
86+
87+
return &OSFile{
88+
BaseFile: BaseFile{filename: fullpath},
89+
file: f,
90+
}, nil
2591
}
2692

27-
// ReadDir returns the filesystem info for all the archives under the
28-
// specified path.
29-
func (o *OS) ReadDir(path string) ([]os.FileInfo, error) {
30-
return ioutil.ReadDir(path)
93+
func (c *OSClient) Stat(filename string) (FileInfo, error) {
94+
fullpath := c.Join(c.RootDir, filename)
95+
return os.Stat(fullpath)
3196
}
3297

3398
// Join joins the specified elements using the filesystem separator.
34-
func (o *OS) Join(elem ...string) string {
99+
func (c *OSClient) Join(elem ...string) string {
35100
return filepath.Join(elem...)
36101
}
102+
103+
func (c *OSClient) Dir(path string) Filesystem {
104+
return NewOSClient(c.Join(c.RootDir, path))
105+
}
106+
107+
func (c *OSClient) Base() string {
108+
return c.RootDir
109+
}
110+
111+
type OSFile struct {
112+
file *os.File
113+
BaseFile
114+
}
115+
116+
func (f *OSFile) Read(p []byte) (int, error) {
117+
return f.file.Read(p)
118+
}
119+
120+
func (f *OSFile) Seek(offset int64, whence int) (int64, error) {
121+
return f.file.Seek(offset, whence)
122+
}
123+
124+
func (f *OSFile) Write(p []byte) (int, error) {
125+
return f.file.Write(p)
126+
}
127+
128+
func (f *OSFile) Close() error {
129+
f.closed = true
130+
131+
return f.file.Close()
132+
}

utils/fs/os_test.go

Lines changed: 29 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -5,147 +5,52 @@ import (
55
"os"
66
"testing"
77

8-
"github.com/alcortesm/tgz"
98
. "gopkg.in/check.v1"
109
)
1110

1211
func Test(t *testing.T) { TestingT(t) }
1312

14-
type FSImplSuite struct {
15-
dir string
16-
}
13+
type WritersSuite struct{}
1714

18-
var _ = Suite(&FSImplSuite{})
15+
var _ = Suite(&WritersSuite{})
1916

20-
func (s *FSImplSuite) SetUpSuite(c *C) {
21-
dir, err := tgz.Extract("../../storage/filesystem/internal/dotgit/fixtures/spinnaker-gc.tgz")
22-
c.Assert(err, IsNil)
23-
s.dir = dir
24-
}
17+
func (s *WritersSuite) TestOSClient_Create(c *C) {
18+
path := getTempDir()
19+
client := NewOSClient(path)
2520

26-
func (s *FSImplSuite) TearDownSuite(c *C) {
27-
err := os.RemoveAll(s.dir)
21+
f, err := client.Create("foo")
2822
c.Assert(err, IsNil)
23+
c.Assert(f.(*OSFile).file.Name(), Equals, f.GetFilename())
2924
}
3025

31-
func (s *FSImplSuite) TestJoin(c *C) {
32-
fs := NewOS()
33-
for i, test := range [...]struct {
34-
input []string
35-
expected string
36-
}{
37-
{
38-
input: []string{},
39-
expected: "",
40-
}, {
41-
input: []string{"a"},
42-
expected: "a",
43-
}, {
44-
input: []string{"a", "b"},
45-
expected: "a/b",
46-
}, {
47-
input: []string{"a", "b", "c"},
48-
expected: "a/b/c",
49-
},
50-
} {
51-
obtained := fs.Join(test.input...)
52-
com := Commentf("test %d:\n\tinput = %v", i, test.input)
53-
c.Assert(obtained, Equals, test.expected, com)
54-
}
55-
}
56-
57-
func (s *FSImplSuite) TestStat(c *C) {
58-
fs := NewOS()
59-
for i, path := range [...]string{
60-
".git/index",
61-
".git/info/refs",
62-
".git/objects/pack/pack-584416f86235cac0d54bfabbdc399fb2b09a5269.pack",
63-
} {
64-
path := fs.Join(s.dir, path)
65-
com := Commentf("test %d", i)
66-
67-
real, err := os.Open(path)
68-
c.Assert(err, IsNil, com)
69-
70-
expected, err := real.Stat()
71-
c.Assert(err, IsNil, com)
72-
73-
obtained, err := fs.Stat(path)
74-
c.Assert(err, IsNil, com)
75-
76-
c.Assert(obtained, DeepEquals, expected, com)
26+
func (s *WritersSuite) TestOSClient_Write(c *C) {
27+
path := getTempDir()
28+
client := NewOSClient(path)
7729

78-
err = real.Close()
79-
c.Assert(err, IsNil, com)
80-
}
81-
}
30+
f, err := client.Create("foo")
31+
c.Assert(err, IsNil)
32+
l, err := f.Write([]byte("foo"))
33+
c.Assert(l, Equals, 3)
34+
c.Assert(err, IsNil)
8235

83-
func (s *FSImplSuite) TestStatErrors(c *C) {
84-
fs := NewOS()
85-
for i, test := range [...]struct {
86-
input string
87-
errRegExp string
88-
}{
89-
{
90-
input: "bla",
91-
errRegExp: ".*bla: no such file or directory",
92-
}, {
93-
input: "bla/foo",
94-
errRegExp: ".*bla/foo: no such file or directory",
95-
},
96-
} {
97-
com := Commentf("test %d", i)
98-
_, err := fs.Stat(test.input)
99-
c.Assert(err, ErrorMatches, test.errRegExp, com)
100-
}
36+
wrote, _ := ioutil.ReadFile(f.(*OSFile).file.Name())
37+
c.Assert(wrote, DeepEquals, []byte("foo"))
10138
}
10239

103-
func (s *FSImplSuite) TestOpen(c *C) {
104-
fs := NewOS()
105-
for i, test := range [...]string{
106-
".git/index",
107-
".git/info/refs",
108-
".git/objects/pack/pack-584416f86235cac0d54bfabbdc399fb2b09a5269.pack",
109-
} {
110-
com := Commentf("test %d", i)
111-
path := fs.Join(s.dir, test)
112-
113-
real, err := os.Open(path)
114-
c.Assert(err, IsNil, com)
115-
realData, err := ioutil.ReadAll(real)
116-
c.Assert(err, IsNil, com)
117-
err = real.Close()
118-
c.Assert(err, IsNil, com)
40+
func (s *WritersSuite) TestOSClient_Close(c *C) {
41+
path := getTempDir()
42+
client := NewOSClient(path)
11943

120-
obtained, err := fs.Open(path)
121-
c.Assert(err, IsNil, com)
122-
obtainedData, err := ioutil.ReadAll(obtained)
123-
c.Assert(err, IsNil, com)
124-
err = obtained.Close()
125-
c.Assert(err, IsNil, com)
44+
f, err := client.Create("foo")
45+
c.Assert(err, IsNil)
46+
f.Write([]byte("foo"))
47+
c.Assert(f.Close(), IsNil)
12648

127-
c.Assert(obtainedData, DeepEquals, realData, com)
128-
}
49+
wrote, _ := ioutil.ReadFile(f.GetFilename())
50+
c.Assert(wrote, DeepEquals, []byte("foo"))
12951
}
13052

131-
func (s *FSImplSuite) TestReadDir(c *C) {
132-
fs := NewOS()
133-
for i, test := range [...]string{
134-
".git/info",
135-
".",
136-
"",
137-
".git/objects",
138-
".git/objects/pack",
139-
} {
140-
com := Commentf("test %d", i)
141-
path := fs.Join(s.dir, test)
142-
143-
expected, err := ioutil.ReadDir(path)
144-
c.Assert(err, IsNil, com)
145-
146-
obtained, err := fs.ReadDir(path)
147-
c.Assert(err, IsNil, com)
148-
149-
c.Assert(obtained, DeepEquals, expected, com)
150-
}
53+
func getTempDir() string {
54+
dir, _ := ioutil.TempDir(os.TempDir(), "--OSClientTest--")
55+
return dir
15156
}

0 commit comments

Comments
 (0)