aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMáximo Cuadros <mcuadros@gmail.com>2016-08-25 17:25:31 +0200
committerMáximo Cuadros <mcuadros@gmail.com>2016-08-25 17:25:31 +0200
commita3418c5e0a3c6e925b5a4fb3ecb1d3db56408d1a (patch)
tree23ab46cb3269a104d9b69e0d1a1bec3c340df112
parent0f97041639b55bc4631145e2053a47a1eb8cdef0 (diff)
downloadgo-git-a3418c5e0a3c6e925b5a4fb3ecb1d3db56408d1a.tar.gz
Repository: Clone protection if non empty object storage, Remote: NoErrAlreadyUpToDate
-rw-r--r--commit_test.go4
-rw-r--r--common_test.go10
-rw-r--r--file_test.go2
-rw-r--r--objects_test.go4
-rw-r--r--remote.go22
-rw-r--r--remote_test.go19
-rw-r--r--repository.go23
-rw-r--r--repository_test.go32
8 files changed, 100 insertions, 16 deletions
diff --git a/commit_test.go b/commit_test.go
index 9a05cd8..626fdcf 100644
--- a/commit_test.go
+++ b/commit_test.go
@@ -15,8 +15,8 @@ type SuiteCommit struct {
var _ = Suite(&SuiteCommit{})
-func (s *SuiteCommit) SetUpTest(c *C) {
- s.BaseSuite.SetUpTest(c)
+func (s *SuiteCommit) SetUpSuite(c *C) {
+ s.BaseSuite.SetUpSuite(c)
hash := core.NewHash("1669dce138d9b841a518c64b10914d88f5e488ea")
diff --git a/common_test.go b/common_test.go
index dbacddd..e02e9d6 100644
--- a/common_test.go
+++ b/common_test.go
@@ -22,7 +22,7 @@ type BaseSuite struct {
Repository *Repository
}
-func (s *BaseSuite) SetUpTest(c *C) {
+func (s *BaseSuite) SetUpSuite(c *C) {
clients.InstallProtocol("mock", func(end common.Endpoint) common.GitUploadPackService {
return &MockGitUploadPackService{endpoint: end}
})
@@ -75,12 +75,16 @@ func (p *MockGitUploadPackService) Info() (*common.GitUploadPackInfo, error) {
}, nil
}
-func (p *MockGitUploadPackService) Fetch(*common.GitUploadPackRequest) (io.ReadCloser, error) {
+func (p *MockGitUploadPackService) Fetch(r *common.GitUploadPackRequest) (io.ReadCloser, error) {
if !p.connected {
return nil, errors.New("not connected")
}
- return os.Open("formats/packfile/fixtures/git-fixture.ref-delta")
+ if len(r.Wants) == 1 {
+ return os.Open("formats/packfile/fixtures/git-fixture.ref-delta")
+ }
+
+ return os.Open("fixtures/pack-63bbc2e1bde392e2205b30fa3584ddb14ef8bd41.pack")
}
func (p *MockGitUploadPackService) Disconnect() error {
diff --git a/file_test.go b/file_test.go
index e49970a..e545d99 100644
--- a/file_test.go
+++ b/file_test.go
@@ -17,6 +17,8 @@ var _ = Suite(&SuiteFile{})
// create the repositories of the fixtures
func (s *SuiteFile) SetUpSuite(c *C) {
+ s.BaseSuite.SetUpSuite(c)
+
fileFixtures := []packedFixture{
{"https://github.com/tyba/git-fixture.git", "formats/packfile/fixtures/git-fixture.ofs-delta"},
{"https://github.com/cpcs499/Final_Pres_P", "formats/packfile/fixtures/Final_Pres_P.ofs-delta"},
diff --git a/objects_test.go b/objects_test.go
index b36bb85..df62fe1 100644
--- a/objects_test.go
+++ b/objects_test.go
@@ -16,8 +16,8 @@ type ObjectsSuite struct {
var _ = Suite(&ObjectsSuite{})
-func (s *ObjectsSuite) SetUpTest(c *C) {
- s.BaseSuite.SetUpTest(c)
+func (s *ObjectsSuite) SetUpSuite(c *C) {
+ s.BaseSuite.SetUpSuite(c)
s.r = NewMemoryRepository()
err := s.r.Clone(&CloneOptions{URL: RepositoryFixture})
diff --git a/remote.go b/remote.go
index a8b77b1..f918f3d 100644
--- a/remote.go
+++ b/remote.go
@@ -1,6 +1,7 @@
package git
import (
+ "errors"
"fmt"
"io"
@@ -11,6 +12,8 @@ import (
"gopkg.in/src-d/go-git.v4/formats/packfile"
)
+var NoErrAlreadyUpToDate = errors.New("already up-to-date")
+
// Remote represents a connection to a remote repository
type Remote struct {
c *config.RemoteConfig
@@ -87,6 +90,10 @@ func (r *Remote) Fetch(o *FetchOptions) (err error) {
return err
}
+ if len(refs) == 0 {
+ return NoErrAlreadyUpToDate
+ }
+
req, err := r.buildRequest(r.s.ReferenceStorage(), o, refs)
if err != nil {
return err
@@ -107,17 +114,22 @@ func (r *Remote) Fetch(o *FetchOptions) (err error) {
func (r *Remote) getWantedReferences(spec []config.RefSpec) ([]*core.Reference, error) {
var refs []*core.Reference
+ return refs, r.Refs().ForEach(func(ref *core.Reference) error {
+ if ref.Type() != core.HashReference {
+ return nil
+ }
- return refs, r.Refs().ForEach(func(r *core.Reference) error {
- if r.Type() != core.HashReference {
+ if !config.MatchAny(spec, ref.Name()) {
return nil
}
- if config.MatchAny(spec, r.Name()) {
- refs = append(refs, r)
+ _, err := r.s.ObjectStorage().Get(ref.Hash())
+ if err == core.ErrObjectNotFound {
+ refs = append(refs, ref)
+ return nil
}
- return nil
+ return err
})
}
diff --git a/remote_test.go b/remote_test.go
index 00766ad..9bafcd1 100644
--- a/remote_test.go
+++ b/remote_test.go
@@ -83,7 +83,24 @@ func (s *RemoteSuite) TestFetch(c *C) {
})
c.Assert(err, IsNil)
- c.Assert(sto.ObjectStorage().(*memory.ObjectStorage).Objects, HasLen, 28)
+ c.Assert(sto.ObjectStorage().(*memory.ObjectStorage).Objects, HasLen, 31)
+}
+
+func (s *RemoteSuite) TestFetchNoErrAlreadyUpToDate(c *C) {
+ sto := memory.NewStorage()
+ r := newRemote(sto, &config.RemoteConfig{Name: "foo", URL: RepositoryFixture})
+ r.upSrv = &MockGitUploadPackService{}
+
+ c.Assert(r.Connect(), IsNil)
+
+ o := &FetchOptions{
+ RefSpecs: []config.RefSpec{config.DefaultRefSpec},
+ }
+
+ err := r.Fetch(o)
+ c.Assert(err, IsNil)
+ err = r.Fetch(o)
+ c.Assert(err, Equals, NoErrAlreadyUpToDate)
}
func (s *RemoteSuite) TestHead(c *C) {
diff --git a/repository.go b/repository.go
index 445e90c..fc871c7 100644
--- a/repository.go
+++ b/repository.go
@@ -12,8 +12,9 @@ import (
)
var (
- ErrObjectNotFound = errors.New("object not found")
- ErrInvalidReference = errors.New("invalid reference, should be a tag or a branch")
+ ErrObjectNotFound = errors.New("object not found")
+ ErrInvalidReference = errors.New("invalid reference, should be a tag or a branch")
+ ErrRepositoryNonEmpty = errors.New("repository non empty")
)
// Repository giturl string, auth common.AuthMethod repository struct
@@ -94,6 +95,15 @@ func (r *Repository) DeleteRemote(name string) error {
// Clone clones a remote repository
func (r *Repository) Clone(o *CloneOptions) error {
+ empty, err := r.IsEmpty()
+ if err != nil {
+ return err
+ }
+
+ if !empty {
+ return ErrRepositoryNonEmpty
+ }
+
if err := o.Validate(); err != nil {
return err
}
@@ -166,6 +176,15 @@ func (r *Repository) createReferences(ref *core.Reference) error {
return r.s.ReferenceStorage().Set(head)
}
+// IsEmpty returns true if the repository is empty
+func (r *Repository) IsEmpty() (bool, error) {
+ var count int
+ return count == 0, r.Refs().ForEach(func(r *core.Reference) error {
+ count++
+ return nil
+ })
+}
+
// Pull incorporates changes from a remote repository into the current branch
func (r *Repository) Pull(o *PullOptions) error {
if err := o.Validate(); err != nil {
diff --git a/repository_test.go b/repository_test.go
index ce53ead..bfb0298 100644
--- a/repository_test.go
+++ b/repository_test.go
@@ -106,6 +106,21 @@ func (s *RepositorySuite) TestClone(c *C) {
c.Assert(branch.Hash().String(), Equals, "e8d3ffab552895c19b9fcf7aa264d277cde33881")
}
+func (s *RepositorySuite) TestCloneNonEmpty(c *C) {
+ r := NewMemoryRepository()
+
+ head, err := r.Head()
+ c.Assert(err, Equals, core.ErrReferenceNotFound)
+ c.Assert(head, IsNil)
+
+ o := &CloneOptions{URL: RepositoryFixture}
+ err = r.Clone(o)
+ c.Assert(err, IsNil)
+
+ err = r.Clone(o)
+ c.Assert(err, Equals, ErrRepositoryNonEmpty)
+}
+
func (s *RepositorySuite) TestCloneSingleBranchAndNonHEAD(c *C) {
r := NewMemoryRepository()
@@ -193,6 +208,21 @@ func (s *RepositorySuite) TestCloneDetachedHEAD(c *C) {
c.Assert(head.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
}
+func (s *RepositorySuite) TestIsEmpty(c *C) {
+ r := NewMemoryRepository()
+
+ empty, err := r.IsEmpty()
+ c.Assert(err, IsNil)
+ c.Assert(empty, Equals, true)
+
+ err = r.Clone(&CloneOptions{URL: RepositoryFixture})
+ c.Assert(err, IsNil)
+
+ empty, err = r.IsEmpty()
+ c.Assert(err, IsNil)
+ c.Assert(empty, Equals, false)
+}
+
func (s *RepositorySuite) TestCommit(c *C) {
r := NewMemoryRepository()
err := r.Clone(&CloneOptions{
@@ -237,7 +267,7 @@ func (s *RepositorySuite) TestCommits(c *C) {
c.Assert(commit.Type(), Equals, core.CommitObject)
}
- c.Assert(count, Equals, 8)
+ c.Assert(count, Equals, 9)
}
func (s *RepositorySuite) TestTag(c *C) {