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

Commit 7bd4f1d

Browse files
authored
utils: fs.TempFile (#88)
* utils: fs generic TestSuite * fs: fs.TempFile * utils: fs small changes requested * utils: fs, test fs.Create overwriting files
1 parent c56b22f commit 7bd4f1d

File tree

5 files changed

+236
-159
lines changed

5 files changed

+236
-159
lines changed

storage/filesystem/internal/dotgit/writers.go

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
package dotgit
22

33
import (
4-
"crypto/sha1"
54
"fmt"
65
"io"
76
"sync/atomic"
8-
"time"
97

108
"gopkg.in/src-d/go-git.v4/core"
119
"gopkg.in/src-d/go-git.v4/formats/idxfile"
@@ -26,15 +24,12 @@ type PackWriter struct {
2624
}
2725

2826
func newPackWrite(fs fs.Filesystem) (*PackWriter, error) {
29-
seed := sha1.Sum([]byte(time.Now().String()))
30-
tmp := fs.Join(objectsPath, packPath, fmt.Sprintf("tmp_pack_%x", seed))
31-
32-
fw, err := fs.Create(tmp)
27+
fw, err := fs.TempFile(fs.Join(objectsPath, packPath), "tmp_pack_")
3328
if err != nil {
3429
return nil, err
3530
}
3631

37-
fr, err := fs.Open(tmp)
32+
fr, err := fs.Open(fw.Filename())
3833
if err != nil {
3934
return nil, err
4035
}
@@ -228,10 +223,7 @@ type ObjectWriter struct {
228223
}
229224

230225
func newObjectWriter(fs fs.Filesystem) (*ObjectWriter, error) {
231-
seed := sha1.Sum([]byte(time.Now().String()))
232-
tmp := fs.Join(objectsPath, fmt.Sprintf("tmp_obj_%x", seed))
233-
234-
f, err := fs.Create(tmp)
226+
f, err := fs.TempFile(fs.Join(objectsPath, packPath), "tmp_obj_")
235227
if err != nil {
236228
return nil, err
237229
}

utils/fs/fs.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ var (
1616
type Filesystem interface {
1717
Create(filename string) (File, error)
1818
Open(filename string) (File, error)
19-
Rename(from, to string) error
2019
Stat(filename string) (FileInfo, error)
2120
ReadDir(path string) ([]FileInfo, error)
21+
TempFile(dir, prefix string) (File, error)
22+
Rename(from, to string) error
2223
Join(elem ...string) string
2324
Dir(path string) Filesystem
2425
Base() string

utils/fs/fs_test.go

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
package fs
2+
3+
import (
4+
"io"
5+
"io/ioutil"
6+
"strings"
7+
"testing"
8+
9+
. "gopkg.in/check.v1"
10+
)
11+
12+
func Test(t *testing.T) { TestingT(t) }
13+
14+
type FilesystemSuite struct {
15+
fs Filesystem
16+
}
17+
18+
func (s *FilesystemSuite) TestCreate(c *C) {
19+
f, err := s.fs.Create("foo")
20+
c.Assert(err, IsNil)
21+
c.Assert(f.Filename(), Equals, "foo")
22+
}
23+
24+
func (s *FilesystemSuite) TestCreateDepth(c *C) {
25+
f, err := s.fs.Create("bar/foo")
26+
c.Assert(err, IsNil)
27+
c.Assert(f.Filename(), Equals, "bar/foo")
28+
}
29+
30+
func (s *FilesystemSuite) TestCreateDepthAbsolute(c *C) {
31+
f, err := s.fs.Create("/bar/foo")
32+
c.Assert(err, IsNil)
33+
c.Assert(f.Filename(), Equals, "bar/foo")
34+
}
35+
36+
func (s *FilesystemSuite) TestCreateAndWrite(c *C) {
37+
f, err := s.fs.Create("foo")
38+
c.Assert(err, IsNil)
39+
l, err := f.Write([]byte("foo"))
40+
c.Assert(err, IsNil)
41+
c.Assert(l, Equals, 3)
42+
43+
f.Seek(0, io.SeekStart)
44+
wrote, err := ioutil.ReadAll(f)
45+
c.Assert(err, IsNil)
46+
c.Assert(wrote, DeepEquals, []byte("foo"))
47+
}
48+
49+
func (s *FilesystemSuite) TestCreateOverwrite(c *C) {
50+
for i := 0; i < 2; i++ {
51+
f, err := s.fs.Create("foo")
52+
c.Assert(err, IsNil)
53+
54+
l, err := f.Write([]byte("foo"))
55+
c.Assert(err, IsNil)
56+
c.Assert(l, Equals, 3)
57+
58+
err = f.Close()
59+
c.Assert(err, IsNil)
60+
}
61+
62+
f, err := s.fs.Open("foo")
63+
c.Assert(err, IsNil)
64+
65+
wrote, err := ioutil.ReadAll(f)
66+
c.Assert(err, IsNil)
67+
c.Assert(wrote, DeepEquals, []byte("foo"))
68+
}
69+
70+
func (s *FilesystemSuite) TestCreateClose(c *C) {
71+
f, err := s.fs.Create("foo")
72+
c.Assert(err, IsNil)
73+
c.Assert(f.IsClosed(), Equals, false)
74+
75+
f.Write([]byte("foo"))
76+
c.Assert(f.Close(), IsNil)
77+
78+
file, err := s.fs.Open(f.Filename())
79+
c.Assert(err, IsNil)
80+
81+
wrote, err := ioutil.ReadAll(file)
82+
c.Assert(err, IsNil)
83+
c.Assert(wrote, DeepEquals, []byte("foo"))
84+
85+
c.Assert(f.IsClosed(), Equals, true)
86+
}
87+
88+
func (s *FilesystemSuite) TestReadDirAndDir(c *C) {
89+
files := []string{"foo", "bar", "qux/baz", "qux/qux"}
90+
for _, name := range files {
91+
f, err := s.fs.Create(name)
92+
c.Assert(err, IsNil)
93+
c.Assert(f.Close(), IsNil)
94+
}
95+
96+
info, err := s.fs.ReadDir("/")
97+
c.Assert(err, IsNil)
98+
c.Assert(info, HasLen, 3)
99+
100+
info, err = s.fs.ReadDir("/qux")
101+
c.Assert(err, IsNil)
102+
c.Assert(info, HasLen, 2)
103+
104+
qux := s.fs.Dir("/qux")
105+
info, err = qux.ReadDir("/")
106+
c.Assert(err, IsNil)
107+
c.Assert(info, HasLen, 2)
108+
}
109+
110+
func (s *FilesystemSuite) TestRename(c *C) {
111+
f, err := s.fs.Create("foo")
112+
c.Assert(err, IsNil)
113+
c.Assert(f.Close(), IsNil)
114+
115+
err = s.fs.Rename("foo", "bar")
116+
c.Assert(err, IsNil)
117+
118+
foo, err := s.fs.Stat("foo")
119+
c.Assert(foo, IsNil)
120+
c.Assert(err, NotNil)
121+
122+
bar, err := s.fs.Stat("bar")
123+
c.Assert(bar, NotNil)
124+
c.Assert(err, IsNil)
125+
}
126+
127+
func (s *FilesystemSuite) TestTempFile(c *C) {
128+
f, err := s.fs.TempFile("", "bar")
129+
c.Assert(err, IsNil)
130+
131+
c.Assert(strings.HasPrefix(f.Filename(), "bar"), Equals, true)
132+
}
133+
134+
func (s *FilesystemSuite) TestTempFileWithPath(c *C) {
135+
f, err := s.fs.TempFile("foo", "bar")
136+
c.Assert(err, IsNil)
137+
138+
c.Assert(strings.HasPrefix(f.Filename(), s.fs.Join("foo", "bar")), Equals, true)
139+
}
140+
141+
func (s *FilesystemSuite) TestTempFileFullWithPath(c *C) {
142+
f, err := s.fs.TempFile("/foo", "bar")
143+
c.Assert(err, IsNil)
144+
145+
c.Assert(strings.HasPrefix(f.Filename(), s.fs.Join("foo", "bar")), Equals, true)
146+
}
147+
148+
func (s *FilesystemSuite) TestOpenAndStat(c *C) {
149+
f, err := s.fs.Create("foo")
150+
c.Assert(err, IsNil)
151+
c.Assert(f.Close(), IsNil)
152+
153+
foo, err := s.fs.Open("foo")
154+
c.Assert(foo, NotNil)
155+
c.Assert(foo.Filename(), Equals, "foo")
156+
c.Assert(err, IsNil)
157+
158+
stat, err := s.fs.Stat("foo")
159+
c.Assert(stat, NotNil)
160+
c.Assert(err, IsNil)
161+
c.Assert(stat.Name(), Equals, "foo")
162+
}
163+
164+
func (s *FilesystemSuite) TestJoin(c *C) {
165+
c.Assert(s.fs.Join("foo", "bar"), Equals, "foo/bar")
166+
}
167+
168+
func (s *FilesystemSuite) TestBase(c *C) {
169+
c.Assert(s.fs.Base(), Not(Equals), "")
170+
}

utils/fs/os.go

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,21 @@ import (
77
"path/filepath"
88
)
99

10-
// OSClient a filesystem based on OSClient
10+
// OS a filesystem base on the os filesystem
1111
type OS struct {
12-
RootDir string
12+
base string
1313
}
1414

15-
// NewOSClient returns a new OSClient
16-
func NewOS(rootDir string) *OS {
15+
// NewOS returns a new OS filesystem
16+
func NewOS(baseDir string) *OS {
1717
return &OS{
18-
RootDir: rootDir,
18+
base: baseDir,
1919
}
2020
}
2121

2222
// Create creates a new GlusterFSFile
2323
func (fs *OS) Create(filename string) (File, error) {
24-
fullpath := path.Join(fs.RootDir, filename)
24+
fullpath := path.Join(fs.base, filename)
2525

2626
if err := fs.createDir(fullpath); err != nil {
2727
return nil, err
@@ -32,6 +32,11 @@ func (fs *OS) Create(filename string) (File, error) {
3232
return nil, err
3333
}
3434

35+
filename, err = filepath.Rel(fs.base, fullpath)
36+
if err != nil {
37+
return nil, err
38+
}
39+
3540
return &OSFile{
3641
BaseFile: BaseFile{filename: filename},
3742
file: f,
@@ -52,7 +57,7 @@ func (fs *OS) createDir(fullpath string) error {
5257
// ReadDir returns the filesystem info for all the archives under the specified
5358
// path.
5459
func (fs *OS) ReadDir(path string) ([]FileInfo, error) {
55-
fullpath := fs.Join(fs.RootDir, path)
60+
fullpath := fs.Join(fs.base, path)
5661

5762
l, err := ioutil.ReadDir(fullpath)
5863
if err != nil {
@@ -68,8 +73,8 @@ func (fs *OS) ReadDir(path string) ([]FileInfo, error) {
6873
}
6974

7075
func (fs *OS) Rename(from, to string) error {
71-
from = fs.Join(fs.RootDir, from)
72-
to = fs.Join(fs.RootDir, to)
76+
from = fs.Join(fs.base, from)
77+
to = fs.Join(fs.base, to)
7378

7479
if err := fs.createDir(to); err != nil {
7580
return err
@@ -78,9 +83,10 @@ func (fs *OS) Rename(from, to string) error {
7883
return os.Rename(from, to)
7984
}
8085

86+
// Open opens the named file for reading. If successful, methods on the returned
87+
// file can be used for reading only.
8188
func (fs *OS) Open(filename string) (File, error) {
82-
fullpath := fs.Join(fs.RootDir, filename)
83-
89+
fullpath := fs.Join(fs.base, filename)
8490
f, err := os.Open(fullpath)
8591
if err != nil {
8692
return nil, err
@@ -92,24 +98,56 @@ func (fs *OS) Open(filename string) (File, error) {
9298
}, nil
9399
}
94100

101+
// Stat returns the FileInfo structure describing file.
95102
func (fs *OS) Stat(filename string) (FileInfo, error) {
96-
fullpath := fs.Join(fs.RootDir, filename)
103+
fullpath := fs.Join(fs.base, filename)
97104
return os.Stat(fullpath)
98105
}
99106

107+
func (fs *OS) TempFile(dir, prefix string) (File, error) {
108+
fullpath := fs.Join(fs.base, dir)
109+
if err := fs.createDir(fullpath + string(os.PathSeparator)); err != nil {
110+
return nil, err
111+
}
112+
113+
f, err := ioutil.TempFile(fullpath, prefix)
114+
if err != nil {
115+
return nil, err
116+
}
117+
118+
s, err := f.Stat()
119+
if err != nil {
120+
return nil, err
121+
}
122+
123+
filename, err := filepath.Rel(fs.base, fs.Join(fullpath, s.Name()))
124+
if err != nil {
125+
return nil, err
126+
}
127+
128+
return &OSFile{
129+
BaseFile: BaseFile{filename: filename},
130+
file: f,
131+
}, nil
132+
}
133+
100134
// Join joins the specified elements using the filesystem separator.
101135
func (fs *OS) Join(elem ...string) string {
102136
return filepath.Join(elem...)
103137
}
104138

139+
// Dir returns a new Filesystem from the same type of fs using as baseDir the
140+
// given path
105141
func (fs *OS) Dir(path string) Filesystem {
106-
return NewOS(fs.Join(fs.RootDir, path))
142+
return NewOS(fs.Join(fs.base, path))
107143
}
108144

145+
// Base returns the base path of the filesytem
109146
func (fs *OS) Base() string {
110-
return fs.RootDir
147+
return fs.base
111148
}
112149

150+
// OSFile represents a file in the os filesystem
113151
type OSFile struct {
114152
file *os.File
115153
BaseFile

0 commit comments

Comments
 (0)