aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plumbing/format/idxfile/decoder_test.go3
-rw-r--r--plumbing/format/idxfile/encoder_test.go3
-rw-r--r--plumbing/object/commit_walker.go8
-rw-r--r--plumbing/object/commit_walker_test.go4
-rw-r--r--plumbing/revlist/revlist.go2
-rw-r--r--plumbing/storer/storer.go8
-rw-r--r--plumbing/transport/file/client.go17
-rw-r--r--plumbing/transport/git/common.go10
-rw-r--r--plumbing/transport/git/receive_pack_test.go140
-rw-r--r--plumbing/transport/internal/common/common.go50
-rw-r--r--plumbing/transport/test/receive_pack.go9
-rw-r--r--remote.go4
-rw-r--r--repository.go19
-rw-r--r--storage/filesystem/internal/dotgit/dotgit.go2
-rw-r--r--storage/filesystem/storage.go14
-rw-r--r--storage/filesystem/storage_test.go19
16 files changed, 243 insertions, 69 deletions
diff --git a/plumbing/format/idxfile/decoder_test.go b/plumbing/format/idxfile/decoder_test.go
index 27aa59b..609f4e3 100644
--- a/plumbing/format/idxfile/decoder_test.go
+++ b/plumbing/format/idxfile/decoder_test.go
@@ -5,10 +5,11 @@ import (
"fmt"
"testing"
- . "gopkg.in/check.v1"
"github.com/src-d/go-git-fixtures"
"gopkg.in/src-d/go-git.v4/plumbing/format/packfile"
"gopkg.in/src-d/go-git.v4/storage/memory"
+
+ . "gopkg.in/check.v1"
)
func Test(t *testing.T) { TestingT(t) }
diff --git a/plumbing/format/idxfile/encoder_test.go b/plumbing/format/idxfile/encoder_test.go
index fab87b3..1fc4e9c 100644
--- a/plumbing/format/idxfile/encoder_test.go
+++ b/plumbing/format/idxfile/encoder_test.go
@@ -4,9 +4,10 @@ import (
"bytes"
"io/ioutil"
- . "gopkg.in/check.v1"
"github.com/src-d/go-git-fixtures"
"gopkg.in/src-d/go-git.v4/plumbing"
+
+ . "gopkg.in/check.v1"
)
func (s *IdxfileSuite) TestEncode(c *C) {
diff --git a/plumbing/object/commit_walker.go b/plumbing/object/commit_walker.go
index 3316fab..8d2c6e8 100644
--- a/plumbing/object/commit_walker.go
+++ b/plumbing/object/commit_walker.go
@@ -13,13 +13,13 @@ type commitPreIterator struct {
start *Commit
}
-// NewCommitPreIterator returns a CommitIter that walks the commit history,
+// NewCommitPreorderIter returns a CommitIter that walks the commit history,
// starting at the given commit and visiting its parents in pre-order.
// The given callback will be called for each visited commit. Each commit will
// be visited only once. If the callback returns an error, walking will stop
// and will return the error. Other errors might be returned if the history
// cannot be traversed (e.g. missing objects).
-func NewCommitPreIterator(c *Commit) CommitIter {
+func NewCommitPreorderIter(c *Commit) CommitIter {
return &commitPreIterator{
seen: make(map[plumbing.Hash]bool),
stack: make([]CommitIter, 0),
@@ -94,12 +94,12 @@ type commitPostIterator struct {
seen map[plumbing.Hash]bool
}
-// NewCommitPostIterator returns a CommitIter that walks the commit
+// NewCommitPostorderIter returns a CommitIter that walks the commit
// history like WalkCommitHistory but in post-order. This means that after
// walking a merge commit, the merged commit will be walked before the base
// it was merged on. This can be useful if you wish to see the history in
// chronological order.
-func NewCommitPostIterator(c *Commit) CommitIter {
+func NewCommitPostorderIter(c *Commit) CommitIter {
return &commitPostIterator{
stack: []*Commit{c},
seen: make(map[plumbing.Hash]bool),
diff --git a/plumbing/object/commit_walker_test.go b/plumbing/object/commit_walker_test.go
index 7d04bce..2a03057 100644
--- a/plumbing/object/commit_walker_test.go
+++ b/plumbing/object/commit_walker_test.go
@@ -12,7 +12,7 @@ func (s *CommitWalkerSuite) TestCommitPreIterator(c *C) {
commit := s.commit(c, s.Fixture.Head)
var commits []*Commit
- wIter := NewCommitPreIterator(commit)
+ wIter := NewCommitPreorderIter(commit)
wIter.ForEach(func(c *Commit) error {
commits = append(commits, c)
return nil
@@ -39,7 +39,7 @@ func (s *CommitWalkerSuite) TestCommitPostIterator(c *C) {
commit := s.commit(c, s.Fixture.Head)
var commits []*Commit
- wIter := NewCommitPostIterator(commit)
+ wIter := NewCommitPostorderIter(commit)
wIter.ForEach(func(c *Commit) error {
commits = append(commits, c)
return nil
diff --git a/plumbing/revlist/revlist.go b/plumbing/revlist/revlist.go
index fbd1bd9..3e02184 100644
--- a/plumbing/revlist/revlist.go
+++ b/plumbing/revlist/revlist.go
@@ -82,7 +82,7 @@ func reachableObjects(
commit *object.Commit,
seen map[plumbing.Hash]bool,
cb func(h plumbing.Hash)) error {
- return object.NewCommitPreIterator(commit).
+ return object.NewCommitPreorderIter(commit).
ForEach(func(commit *object.Commit) error {
if seen[commit.Hash] {
return nil
diff --git a/plumbing/storer/storer.go b/plumbing/storer/storer.go
index 0b96c0e..c7bc65a 100644
--- a/plumbing/storer/storer.go
+++ b/plumbing/storer/storer.go
@@ -5,3 +5,11 @@ type Storer interface {
EncodedObjectStorer
ReferenceStorer
}
+
+// Initializer should be implemented by storers that require to perform any
+// operation when creating a new repository (i.e. git init).
+type Initializer interface {
+ // Init performs initialization of the storer and returns the error, if
+ // any.
+ Init() error
+}
diff --git a/plumbing/transport/file/client.go b/plumbing/transport/file/client.go
index d2a57d0..a199b01 100644
--- a/plumbing/transport/file/client.go
+++ b/plumbing/transport/file/client.go
@@ -3,6 +3,7 @@ package file
import (
"io"
+ "os"
"os/exec"
"gopkg.in/src-d/go-git.v4/plumbing/transport"
@@ -71,10 +72,16 @@ func (c *command) Close() error {
return nil
}
- return c.cmd.Process.Kill()
-}
-
-func (c *command) Wait() error {
defer func() { c.closed = true }()
- return c.cmd.Wait()
+ err := c.cmd.Wait()
+ if _, ok := err.(*os.PathError); ok {
+ return nil
+ }
+
+ // When a repository does not exist, the command exits with code 128.
+ if _, ok := err.(*exec.ExitError); ok {
+ return nil
+ }
+
+ return err
}
diff --git a/plumbing/transport/git/common.go b/plumbing/transport/git/common.go
index 753f125..fcd02f8 100644
--- a/plumbing/transport/git/common.go
+++ b/plumbing/transport/git/common.go
@@ -90,12 +90,12 @@ func (c *command) StdoutPipe() (io.Reader, error) {
}
func endpointToCommand(cmd string, ep transport.Endpoint) string {
- return fmt.Sprintf("%s %s%chost=%s%c", cmd, ep.Path(), 0, ep.Host(), 0)
-}
+ host := ep.Host()
+ if ep.Port() != DefaultPort {
+ host = fmt.Sprintf("%s:%d", ep.Host(), ep.Port())
+ }
-// Wait no-op function, required by the interface
-func (c *command) Wait() error {
- return nil
+ return fmt.Sprintf("%s %s%chost=%s%c", cmd, ep.Path(), 0, host, 0)
}
// Close closes the TCP connection and connection.
diff --git a/plumbing/transport/git/receive_pack_test.go b/plumbing/transport/git/receive_pack_test.go
new file mode 100644
index 0000000..d73966e
--- /dev/null
+++ b/plumbing/transport/git/receive_pack_test.go
@@ -0,0 +1,140 @@
+package git
+
+import (
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "github.com/src-d/go-git-fixtures"
+ "gopkg.in/src-d/go-git.v4/plumbing/transport"
+ "gopkg.in/src-d/go-git.v4/plumbing/transport/test"
+
+ . "gopkg.in/check.v1"
+)
+
+type ReceivePackSuite struct {
+ test.ReceivePackSuite
+ fixtures.Suite
+
+ base string
+ daemon *exec.Cmd
+}
+
+var _ = Suite(&ReceivePackSuite{})
+
+func (s *ReceivePackSuite) SetUpTest(c *C) {
+ s.ReceivePackSuite.Client = DefaultClient
+
+ port, err := freePort()
+ c.Assert(err, IsNil)
+
+ base, err := ioutil.TempDir(os.TempDir(), "go-git-daemon-test")
+ c.Assert(err, IsNil)
+ s.base = base
+
+ host := fmt.Sprintf("localhost_%d", port)
+ interpolatedBase := filepath.Join(base, host)
+ err = os.MkdirAll(interpolatedBase, 0755)
+ c.Assert(err, IsNil)
+
+ dotgit := fixtures.Basic().One().DotGit().Base()
+ prepareRepo(c, dotgit)
+ err = os.Rename(dotgit, filepath.Join(interpolatedBase, "basic.git"))
+ c.Assert(err, IsNil)
+
+ ep, err := transport.NewEndpoint(fmt.Sprintf("git://localhost:%d/basic.git", port))
+ c.Assert(err, IsNil)
+ s.ReceivePackSuite.Endpoint = ep
+
+ dotgit = fixtures.ByTag("empty").One().DotGit().Base()
+ prepareRepo(c, dotgit)
+ err = os.Rename(dotgit, filepath.Join(interpolatedBase, "empty.git"))
+ c.Assert(err, IsNil)
+
+ ep, err = transport.NewEndpoint(fmt.Sprintf("git://localhost:%d/empty.git", port))
+ c.Assert(err, IsNil)
+ s.ReceivePackSuite.EmptyEndpoint = ep
+
+ ep, err = transport.NewEndpoint(fmt.Sprintf("git://localhost:%d/non-existent.git", port))
+ c.Assert(err, IsNil)
+ s.ReceivePackSuite.NonExistentEndpoint = ep
+
+ s.daemon = exec.Command(
+ "git",
+ "daemon",
+ fmt.Sprintf("--base-path=%s", base),
+ "--export-all",
+ "--enable=receive-pack",
+ "--reuseaddr",
+ fmt.Sprintf("--port=%d", port),
+ // Use interpolated paths to validate that clients are specifying
+ // host and port properly.
+ // Note that some git versions (e.g. v2.11.0) had a bug that prevented
+ // the use of repository paths containing colons (:), so we use
+ // underscore (_) instead of colon in the interpolation.
+ // See https://github.com/git/git/commit/fe050334074c5132d01e1df2c1b9a82c9b8d394c
+ fmt.Sprintf("--interpolated-path=%s/%%H_%%P%%D", base),
+ // Unless max-connections is limited to 1, a git-receive-pack
+ // might not be seen by a subsequent operation.
+ "--max-connections=1",
+ // Whitelist required for interpolated paths.
+ fmt.Sprintf("%s/%s", interpolatedBase, "basic.git"),
+ fmt.Sprintf("%s/%s", interpolatedBase, "empty.git"),
+ )
+
+ // Environment must be inherited in order to acknowledge GIT_EXEC_PATH if set.
+ s.daemon.Env = os.Environ()
+
+ err = s.daemon.Start()
+ c.Assert(err, IsNil)
+
+ // Connections might be refused if we start sending request too early.
+ time.Sleep(time.Millisecond * 500)
+}
+
+func (s *ReceivePackSuite) TearDownTest(c *C) {
+ err := s.daemon.Process.Signal(os.Interrupt)
+ c.Assert(err, IsNil)
+ _ = s.daemon.Wait()
+ err = os.RemoveAll(s.base)
+ c.Assert(err, IsNil)
+}
+
+func freePort() (int, error) {
+ addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
+ if err != nil {
+ return 0, err
+ }
+
+ l, err := net.ListenTCP("tcp", addr)
+ if err != nil {
+ return 0, err
+ }
+
+ return l.Addr().(*net.TCPAddr).Port, l.Close()
+}
+
+const bareConfig = `[core]
+repositoryformatversion = 0
+filemode = true
+bare = true`
+
+func prepareRepo(c *C, path string) {
+ // git-receive-pack refuses to update refs/heads/master on non-bare repo
+ // so we ensure bare repo config.
+ config := filepath.Join(path, "config")
+ if _, err := os.Stat(config); err == nil {
+ f, err := os.OpenFile(config, os.O_TRUNC|os.O_WRONLY, 0)
+ c.Assert(err, IsNil)
+ content := strings.NewReader(bareConfig)
+ _, err = io.Copy(f, content)
+ c.Assert(err, IsNil)
+ c.Assert(f.Close(), IsNil)
+ }
+}
diff --git a/plumbing/transport/internal/common/common.go b/plumbing/transport/internal/common/common.go
index f67ae29..c1e1518 100644
--- a/plumbing/transport/internal/common/common.go
+++ b/plumbing/transport/internal/common/common.go
@@ -59,14 +59,8 @@ type Command interface {
// Start starts the specified command. It does not wait for it to
// complete.
Start() error
- // Wait waits for the command to exit. It must have been started by
- // Start. The returned error is nil if the command runs, has no
- // problems copying stdin, stdout, and stderr, and exits with a zero
- // exit status.
- Wait() error
// Close closes the command and releases any resources used by it. It
- // can be called to forcibly finish the command without calling to Wait
- // or to release resources after calling Wait.
+ // will block until the command exits.
Close() error
}
@@ -178,6 +172,7 @@ func (s *session) handleAdvRefDecodeError(err error) error {
// If repository is not found, we get empty stdout and server writes an
// error to stderr.
if err == packp.ErrEmptyInput {
+ s.finished = true
if err := s.checkNotFoundError(); err != nil {
return err
}
@@ -246,9 +241,7 @@ func (s *session) UploadPack(req *packp.UploadPackRequest) (*packp.UploadPackRes
return nil, err
}
- wc := &waitCloser{s.Command}
- rc := ioutil.NewReadCloser(r, wc)
-
+ rc := ioutil.NewReadCloser(r, s.Command)
return DecodeUploadPackResponse(rc, req)
}
@@ -263,10 +256,14 @@ func (s *session) ReceivePack(req *packp.ReferenceUpdateRequest) (*packp.ReportS
return nil, err
}
+ if err := s.Stdin.Close(); err != nil {
+ return nil, err
+ }
+
if !req.Capabilities.Supports(capability.ReportStatus) {
// If we have neither report-status or sideband, we can only
// check return value error.
- return nil, s.Command.Wait()
+ return nil, s.Command.Close()
}
report := packp.NewReportStatus()
@@ -278,7 +275,7 @@ func (s *session) ReceivePack(req *packp.ReferenceUpdateRequest) (*packp.ReportS
return report, err
}
- return report, s.Command.Wait()
+ return report, s.Command.Close()
}
func (s *session) finish() error {
@@ -302,7 +299,7 @@ func (s *session) finish() error {
func (s *session) Close() error {
if err := s.finish(); err != nil {
_ = s.Command.Close()
- return nil
+ return err
}
return s.Command.Close()
@@ -329,10 +326,12 @@ func (s *session) checkNotFoundError() error {
}
var (
- githubRepoNotFoundErr = "ERROR: Repository not found."
- bitbucketRepoNotFoundErr = "conq: repository does not exist."
- localRepoNotFoundErr = "does not appear to be a git repository"
- gitProtocolNotFoundErr = "ERR \n Repository not found."
+ githubRepoNotFoundErr = "ERROR: Repository not found."
+ bitbucketRepoNotFoundErr = "conq: repository does not exist."
+ localRepoNotFoundErr = "does not appear to be a git repository"
+ gitProtocolNotFoundErr = "ERR \n Repository not found."
+ gitProtocolNoSuchErr = "ERR no such repository"
+ gitProtocolAccessDeniedErr = "ERR access denied"
)
func isRepoNotFoundError(s string) bool {
@@ -352,6 +351,14 @@ func isRepoNotFoundError(s string) bool {
return true
}
+ if strings.HasPrefix(s, gitProtocolNoSuchErr) {
+ return true
+ }
+
+ if strings.HasPrefix(s, gitProtocolAccessDeniedErr) {
+ return true
+ }
+
return false
}
@@ -403,12 +410,3 @@ func DecodeUploadPackResponse(r io.ReadCloser, req *packp.UploadPackRequest) (
return res, nil
}
-
-type waitCloser struct {
- Command Command
-}
-
-// Close waits until the command exits and returns error, if any.
-func (c *waitCloser) Close() error {
- return c.Command.Wait()
-}
diff --git a/plumbing/transport/test/receive_pack.go b/plumbing/transport/test/receive_pack.go
index f4be8c8..bb1c58a 100644
--- a/plumbing/transport/test/receive_pack.go
+++ b/plumbing/transport/test/receive_pack.go
@@ -39,10 +39,10 @@ func (s *ReceivePackSuite) TestAdvertisedReferencesEmpty(c *C) {
func (s *ReceivePackSuite) TestAdvertisedReferencesNotExists(c *C) {
r, err := s.Client.NewReceivePackSession(s.NonExistentEndpoint, s.EmptyAuth)
c.Assert(err, IsNil)
- defer func() { c.Assert(r.Close(), IsNil) }()
ar, err := r.AdvertisedReferences()
c.Assert(err, Equals, transport.ErrRepositoryNotFound)
c.Assert(ar, IsNil)
+ c.Assert(r.Close(), IsNil)
r, err = s.Client.NewReceivePackSession(s.NonExistentEndpoint, s.EmptyAuth)
c.Assert(err, IsNil)
@@ -54,6 +54,7 @@ func (s *ReceivePackSuite) TestAdvertisedReferencesNotExists(c *C) {
writer, err := r.ReceivePack(req)
c.Assert(err, Equals, transport.ErrRepositoryNotFound)
c.Assert(writer, IsNil)
+ c.Assert(r.Close(), IsNil)
}
func (s *ReceivePackSuite) TestCallAdvertisedReferenceTwice(c *C) {
@@ -270,7 +271,6 @@ func (s *ReceivePackSuite) TestSendPackAddDeleteReference(c *C) {
func (s *ReceivePackSuite) testSendPackAddReference(c *C) {
r, err := s.Client.NewReceivePackSession(s.Endpoint, s.EmptyAuth)
c.Assert(err, IsNil)
- defer func() { c.Assert(r.Close(), IsNil) }()
fixture := fixtures.Basic().ByTag("packfile").One()
@@ -285,6 +285,8 @@ func (s *ReceivePackSuite) testSendPackAddReference(c *C) {
req.Capabilities.Set(capability.ReportStatus)
}
+ c.Assert(r.Close(), IsNil)
+
s.receivePack(c, s.Endpoint, req, nil, false)
s.checkRemoteReference(c, s.Endpoint, "refs/heads/newbranch", fixture.Head)
}
@@ -292,7 +294,6 @@ func (s *ReceivePackSuite) testSendPackAddReference(c *C) {
func (s *ReceivePackSuite) testSendPackDeleteReference(c *C) {
r, err := s.Client.NewReceivePackSession(s.Endpoint, s.EmptyAuth)
c.Assert(err, IsNil)
- defer func() { c.Assert(r.Close(), IsNil) }()
fixture := fixtures.Basic().ByTag("packfile").One()
@@ -307,6 +308,8 @@ func (s *ReceivePackSuite) testSendPackDeleteReference(c *C) {
req.Capabilities.Set(capability.ReportStatus)
}
+ c.Assert(r.Close(), IsNil)
+
s.receivePack(c, s.Endpoint, req, nil, false)
s.checkRemoteReference(c, s.Endpoint, "refs/heads/newbranch", plumbing.ZeroHash)
}
diff --git a/remote.go b/remote.go
index 592f7b6..deb8d7f 100644
--- a/remote.go
+++ b/remote.go
@@ -76,6 +76,8 @@ func (r *Remote) Push(o *PushOptions) (err error) {
return err
}
+ defer ioutil.CheckClose(s, &err)
+
ar, err := s.AdvertisedReferences()
if err != nil {
return err
@@ -420,7 +422,7 @@ func isFastForward(s storer.EncodedObjectStorer, old, new plumbing.Hash) (bool,
}
found := false
- iter := object.NewCommitPreIterator(c)
+ iter := object.NewCommitPreorderIter(c)
return found, iter.ForEach(func(c *object.Commit) error {
if c.Hash != old {
return nil
diff --git a/repository.go b/repository.go
index 76be660..a3e441b 100644
--- a/repository.go
+++ b/repository.go
@@ -44,6 +44,10 @@ type Repository struct {
// The worktree Filesystem is optional, if nil a bare repository is created. If
// the given storer is not empty ErrRepositoryAlreadyExists is returned
func Init(s storage.Storer, worktree billy.Filesystem) (*Repository, error) {
+ if err := initStorer(s); err != nil {
+ return nil, err
+ }
+
r := newRepository(s, worktree)
_, err := r.Reference(plumbing.HEAD, false)
switch err {
@@ -67,6 +71,15 @@ func Init(s storage.Storer, worktree billy.Filesystem) (*Repository, error) {
return r, setWorktreeAndStoragePaths(r, worktree)
}
+func initStorer(s storer.Storer) error {
+ i, ok := s.(storer.Initializer)
+ if !ok {
+ return nil
+ }
+
+ return i.Init()
+}
+
func setWorktreeAndStoragePaths(r *Repository, worktree billy.Filesystem) error {
type fsBased interface {
Filesystem() billy.Filesystem
@@ -681,7 +694,7 @@ func (r *Repository) Log(o *LogOptions) (object.CommitIter, error) {
return nil, err
}
- return object.NewCommitPreIterator(commit), nil
+ return object.NewCommitPreorderIter(commit), nil
}
// Tags returns all the References from Tags. This method returns all the tag
@@ -914,7 +927,7 @@ func (r *Repository) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, err
commit = c
}
case revision.CaretReg:
- history := object.NewCommitPreIterator(commit)
+ history := object.NewCommitPreorderIter(commit)
re := item.(revision.CaretReg).Regexp
negate := item.(revision.CaretReg).Negate
@@ -944,7 +957,7 @@ func (r *Repository) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, err
commit = c
case revision.AtDate:
- history := object.NewCommitPreIterator(commit)
+ history := object.NewCommitPreorderIter(commit)
date := item.(revision.AtDate).Date
diff --git a/storage/filesystem/internal/dotgit/dotgit.go b/storage/filesystem/internal/dotgit/dotgit.go
index 7db5aa6..827c18d 100644
--- a/storage/filesystem/internal/dotgit/dotgit.go
+++ b/storage/filesystem/internal/dotgit/dotgit.go
@@ -231,7 +231,7 @@ func (d *DotGit) Objects() ([]plumbing.Hash, error) {
return objects, nil
}
-// Object return a fs.File poiting the object file, if exists
+// Object return a fs.File pointing the object file, if exists
func (d *DotGit) Object(h plumbing.Hash) (billy.File, error) {
hash := h.String()
file := d.fs.Join(objectsPath, hash[0:2], hash[2:40])
diff --git a/storage/filesystem/storage.go b/storage/filesystem/storage.go
index dcb061d..768238e 100644
--- a/storage/filesystem/storage.go
+++ b/storage/filesystem/storage.go
@@ -11,7 +11,8 @@ import (
// standard git format (this is, the .git directory). Zero values of this type
// are not safe to use, see the NewStorage function below.
type Storage struct {
- fs billy.Filesystem
+ fs billy.Filesystem
+ dir *dotgit.DotGit
ObjectStorage
ReferenceStorage
@@ -24,17 +25,14 @@ type Storage struct {
// NewStorage returns a new Storage backed by a given `fs.Filesystem`
func NewStorage(fs billy.Filesystem) (*Storage, error) {
dir := dotgit.New(fs)
- if err := dir.Initialize(); err != nil {
- return nil, err
- }
-
o, err := newObjectStorage(dir)
if err != nil {
return nil, err
}
return &Storage{
- fs: fs,
+ fs: fs,
+ dir: dir,
ObjectStorage: o,
ReferenceStorage: ReferenceStorage{dir: dir},
@@ -49,3 +47,7 @@ func NewStorage(fs billy.Filesystem) (*Storage, error) {
func (s *Storage) Filesystem() billy.Filesystem {
return s.fs
}
+
+func (s *Storage) Init() error {
+ return s.dir.Initialize()
+}
diff --git a/storage/filesystem/storage_test.go b/storage/filesystem/storage_test.go
index 0127489..03d2e86 100644
--- a/storage/filesystem/storage_test.go
+++ b/storage/filesystem/storage_test.go
@@ -1,6 +1,7 @@
package filesystem
import (
+ "io/ioutil"
"testing"
"gopkg.in/src-d/go-git.v4/storage/test"
@@ -14,31 +15,29 @@ func Test(t *testing.T) { TestingT(t) }
type StorageSuite struct {
test.BaseStorageSuite
+ dir string
}
var _ = Suite(&StorageSuite{})
func (s *StorageSuite) SetUpTest(c *C) {
- storage, err := NewStorage(osfs.New(c.MkDir()))
+ s.dir = c.MkDir()
+ storage, err := NewStorage(osfs.New(s.dir))
c.Assert(err, IsNil)
s.BaseStorageSuite = test.NewBaseStorageSuite(storage)
}
-func (s *StorageSuite) TestNewStorage(c *C) {
+func (s *StorageSuite) TestFilesystem(c *C) {
fs := memfs.New()
storage, err := NewStorage(fs)
c.Assert(err, IsNil)
- c.Assert(storage, NotNil)
- _, err = fs.Stat("refs/tags")
- c.Assert(err, IsNil)
+ c.Assert(storage.Filesystem(), Equals, fs)
}
-func (s *StorageSuite) TestFilesystem(c *C) {
- fs := memfs.New()
- storage, err := NewStorage(fs)
+func (s *StorageSuite) TestNewStorageShouldNotAddAnyContentsToDir(c *C) {
+ fis, err := ioutil.ReadDir(s.dir)
c.Assert(err, IsNil)
-
- c.Assert(storage.Filesystem(), Equals, fs)
+ c.Assert(fis, HasLen, 0)
}