Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 3 additions & 11 deletions storage/filesystem/internal/dotgit/writers.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package dotgit

import (
"crypto/sha1"
"fmt"
"io"
"sync/atomic"
"time"

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

func newPackWrite(fs fs.Filesystem) (*PackWriter, error) {
seed := sha1.Sum([]byte(time.Now().String()))
tmp := fs.Join(objectsPath, packPath, fmt.Sprintf("tmp_pack_%x", seed))

fw, err := fs.Create(tmp)
fw, err := fs.TempFile(fs.Join(objectsPath, packPath), "tmp_pack_")
if err != nil {
return nil, err
}

fr, err := fs.Open(tmp)
fr, err := fs.Open(fw.Filename())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TempFile already returns a File, do we really need to open it again?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, as I explained in RealWorld

if err != nil {
return nil, err
}
Expand Down Expand Up @@ -228,10 +223,7 @@ type ObjectWriter struct {
}

func newObjectWriter(fs fs.Filesystem) (*ObjectWriter, error) {
seed := sha1.Sum([]byte(time.Now().String()))
tmp := fs.Join(objectsPath, fmt.Sprintf("tmp_obj_%x", seed))

f, err := fs.Create(tmp)
f, err := fs.TempFile(fs.Join(objectsPath, packPath), "tmp_obj_")
if err != nil {
return nil, err
}
Expand Down
3 changes: 2 additions & 1 deletion utils/fs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ var (
type Filesystem interface {
Create(filename string) (File, error)
Open(filename string) (File, error)
Rename(from, to string) error
Stat(filename string) (FileInfo, error)
ReadDir(path string) ([]FileInfo, error)
TempFile(dir, prefix string) (File, error)
Rename(from, to string) error
Join(elem ...string) string
Dir(path string) Filesystem
Base() string
Expand Down
170 changes: 170 additions & 0 deletions utils/fs/fs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package fs

import (
"io"
"io/ioutil"
"strings"
"testing"

. "gopkg.in/check.v1"
)

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

type FilesystemSuite struct {
fs Filesystem
}

func (s *FilesystemSuite) TestCreate(c *C) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create should truncate files if they already exists, I don't think that behavior is being tested.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

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) TestCreateAndWrite(c *C) {
f, err := s.fs.Create("foo")
c.Assert(err, IsNil)
l, err := f.Write([]byte("foo"))
c.Assert(err, IsNil)
c.Assert(l, Equals, 3)

f.Seek(0, io.SeekStart)
wrote, err := ioutil.ReadAll(f)
c.Assert(err, IsNil)
c.Assert(wrote, DeepEquals, []byte("foo"))
}

func (s *FilesystemSuite) TestCreateOverwrite(c *C) {
for i := 0; i < 2; i++ {
f, err := s.fs.Create("foo")
c.Assert(err, IsNil)

l, err := f.Write([]byte("foo"))
c.Assert(err, IsNil)
c.Assert(l, Equals, 3)

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(wrote, DeepEquals, []byte("foo"))
}

func (s *FilesystemSuite) TestCreateClose(c *C) {
f, err := s.fs.Create("foo")
c.Assert(err, IsNil)
c.Assert(f.IsClosed(), Equals, false)

f.Write([]byte("foo"))
c.Assert(f.Close(), IsNil)

file, err := s.fs.Open(f.Filename())
c.Assert(err, IsNil)

wrote, err := ioutil.ReadAll(file)
c.Assert(err, IsNil)
c.Assert(wrote, DeepEquals, []byte("foo"))

c.Assert(f.IsClosed(), Equals, true)
}

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) 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) 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) 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), "")
}
66 changes: 52 additions & 14 deletions utils/fs/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,21 @@ import (
"path/filepath"
)

// OSClient a filesystem based on OSClient
// OS a filesystem base on the os filesystem
type OS struct {
RootDir string
base string
}

// NewOSClient returns a new OSClient
func NewOS(rootDir string) *OS {
// NewOS returns a new OS filesystem
func NewOS(baseDir string) *OS {
return &OS{
RootDir: rootDir,
base: baseDir,
}
}

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

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

filename, err = filepath.Rel(fs.base, fullpath)
if err != nil {
return nil, err
}

return &OSFile{
BaseFile: BaseFile{filename: filename},
file: f,
Expand All @@ -52,7 +57,7 @@ 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.RootDir, path)
fullpath := fs.Join(fs.base, path)

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

func (fs *OS) Rename(from, to string) error {
from = fs.Join(fs.RootDir, from)
to = fs.Join(fs.RootDir, to)
from = fs.Join(fs.base, from)
to = fs.Join(fs.base, to)

if err := fs.createDir(to); err != nil {
return err
Expand All @@ -78,9 +83,10 @@ 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.RootDir, filename)

fullpath := fs.Join(fs.base, filename)
f, err := os.Open(fullpath)
if err != nil {
return nil, err
Expand All @@ -92,24 +98,56 @@ func (fs *OS) Open(filename string) (File, error) {
}, nil
}

// Stat returns the FileInfo structure describing file.
func (fs *OS) Stat(filename string) (FileInfo, error) {
fullpath := fs.Join(fs.RootDir, filename)
fullpath := fs.Join(fs.base, filename)
return os.Stat(fullpath)
}

func (fs *OS) TempFile(dir, prefix string) (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 &OSFile{
BaseFile: BaseFile{filename: filename},
file: 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) Filesystem {
return NewOS(fs.Join(fs.RootDir, path))
return NewOS(fs.Join(fs.base, path))
}

// Base returns the base path of the filesytem
func (fs *OS) Base() string {
return fs.RootDir
return fs.base
}

// OSFile represents a file in the os filesystem
type OSFile struct {
file *os.File
BaseFile
Expand Down
Loading