diff options
author | Máximo Cuadros <mcuadros@gmail.com> | 2016-08-25 17:25:31 +0200 |
---|---|---|
committer | Máximo Cuadros <mcuadros@gmail.com> | 2016-08-25 17:25:31 +0200 |
commit | a3418c5e0a3c6e925b5a4fb3ecb1d3db56408d1a (patch) | |
tree | 23ab46cb3269a104d9b69e0d1a1bec3c340df112 | |
parent | 0f97041639b55bc4631145e2053a47a1eb8cdef0 (diff) | |
download | go-git-a3418c5e0a3c6e925b5a4fb3ecb1d3db56408d1a.tar.gz |
Repository: Clone protection if non empty object storage, Remote: NoErrAlreadyUpToDate
-rw-r--r-- | commit_test.go | 4 | ||||
-rw-r--r-- | common_test.go | 10 | ||||
-rw-r--r-- | file_test.go | 2 | ||||
-rw-r--r-- | objects_test.go | 4 | ||||
-rw-r--r-- | remote.go | 22 | ||||
-rw-r--r-- | remote_test.go | 19 | ||||
-rw-r--r-- | repository.go | 23 | ||||
-rw-r--r-- | repository_test.go | 32 |
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}) @@ -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) { |