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

Commit b7c471f

Browse files
committed
Repository: Clone protection if non empty object storage, Remote: NoErrAlreadyUpToDate
1 parent 5135923 commit b7c471f

9 files changed

+100
-16
lines changed

commit_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ type SuiteCommit struct {
1515

1616
var _ = Suite(&SuiteCommit{})
1717

18-
func (s *SuiteCommit) SetUpTest(c *C) {
19-
s.BaseSuite.SetUpTest(c)
18+
func (s *SuiteCommit) SetUpSuite(c *C) {
19+
s.BaseSuite.SetUpSuite(c)
2020

2121
hash := core.NewHash("1669dce138d9b841a518c64b10914d88f5e488ea")
2222

common_test.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type BaseSuite struct {
2222
Repository *Repository
2323
}
2424

25-
func (s *BaseSuite) SetUpTest(c *C) {
25+
func (s *BaseSuite) SetUpSuite(c *C) {
2626
clients.InstallProtocol("mock", func(end common.Endpoint) common.GitUploadPackService {
2727
return &MockGitUploadPackService{endpoint: end}
2828
})
@@ -75,12 +75,16 @@ func (p *MockGitUploadPackService) Info() (*common.GitUploadPackInfo, error) {
7575
}, nil
7676
}
7777

78-
func (p *MockGitUploadPackService) Fetch(*common.GitUploadPackRequest) (io.ReadCloser, error) {
78+
func (p *MockGitUploadPackService) Fetch(r *common.GitUploadPackRequest) (io.ReadCloser, error) {
7979
if !p.connected {
8080
return nil, errors.New("not connected")
8181
}
8282

83-
return os.Open("formats/packfile/fixtures/git-fixture.ref-delta")
83+
if len(r.Wants) == 1 {
84+
return os.Open("formats/packfile/fixtures/git-fixture.ref-delta")
85+
}
86+
87+
return os.Open("fixtures/pack-63bbc2e1bde392e2205b30fa3584ddb14ef8bd41.pack")
8488
}
8589

8690
func (p *MockGitUploadPackService) Disconnect() error {

file_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ var _ = Suite(&SuiteFile{})
1717

1818
// create the repositories of the fixtures
1919
func (s *SuiteFile) SetUpSuite(c *C) {
20+
s.BaseSuite.SetUpSuite(c)
21+
2022
fileFixtures := []packedFixture{
2123
{"https://github.com/tyba/git-fixture.git", "formats/packfile/fixtures/git-fixture.ofs-delta"},
2224
{"https://github.com/cpcs499/Final_Pres_P", "formats/packfile/fixtures/Final_Pres_P.ofs-delta"},
Binary file not shown.

objects_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ type ObjectsSuite struct {
1616

1717
var _ = Suite(&ObjectsSuite{})
1818

19-
func (s *ObjectsSuite) SetUpTest(c *C) {
20-
s.BaseSuite.SetUpTest(c)
19+
func (s *ObjectsSuite) SetUpSuite(c *C) {
20+
s.BaseSuite.SetUpSuite(c)
2121

2222
s.r = NewMemoryRepository()
2323
err := s.r.Clone(&CloneOptions{URL: RepositoryFixture})

remote.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package git
22

33
import (
4+
"errors"
45
"fmt"
56
"io"
67

@@ -11,6 +12,8 @@ import (
1112
"gopkg.in/src-d/go-git.v4/formats/packfile"
1213
)
1314

15+
var NoErrAlreadyUpToDate = errors.New("already up-to-date")
16+
1417
// Remote represents a connection to a remote repository
1518
type Remote struct {
1619
c *config.RemoteConfig
@@ -87,6 +90,10 @@ func (r *Remote) Fetch(o *FetchOptions) (err error) {
8790
return err
8891
}
8992

93+
if len(refs) == 0 {
94+
return NoErrAlreadyUpToDate
95+
}
96+
9097
req, err := r.buildRequest(r.s.ReferenceStorage(), o, refs)
9198
if err != nil {
9299
return err
@@ -107,17 +114,22 @@ func (r *Remote) Fetch(o *FetchOptions) (err error) {
107114

108115
func (r *Remote) getWantedReferences(spec []config.RefSpec) ([]*core.Reference, error) {
109116
var refs []*core.Reference
117+
return refs, r.Refs().ForEach(func(ref *core.Reference) error {
118+
if ref.Type() != core.HashReference {
119+
return nil
120+
}
110121

111-
return refs, r.Refs().ForEach(func(r *core.Reference) error {
112-
if r.Type() != core.HashReference {
122+
if !config.MatchAny(spec, ref.Name()) {
113123
return nil
114124
}
115125

116-
if config.MatchAny(spec, r.Name()) {
117-
refs = append(refs, r)
126+
_, err := r.s.ObjectStorage().Get(ref.Hash())
127+
if err == core.ErrObjectNotFound {
128+
refs = append(refs, ref)
129+
return nil
118130
}
119131

120-
return nil
132+
return err
121133
})
122134
}
123135

remote_test.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,24 @@ func (s *RemoteSuite) TestFetch(c *C) {
8383
})
8484

8585
c.Assert(err, IsNil)
86-
c.Assert(sto.ObjectStorage().(*memory.ObjectStorage).Objects, HasLen, 28)
86+
c.Assert(sto.ObjectStorage().(*memory.ObjectStorage).Objects, HasLen, 31)
87+
}
88+
89+
func (s *RemoteSuite) TestFetchNoErrAlreadyUpToDate(c *C) {
90+
sto := memory.NewStorage()
91+
r := newRemote(sto, &config.RemoteConfig{Name: "foo", URL: RepositoryFixture})
92+
r.upSrv = &MockGitUploadPackService{}
93+
94+
c.Assert(r.Connect(), IsNil)
95+
96+
o := &FetchOptions{
97+
RefSpecs: []config.RefSpec{config.DefaultRefSpec},
98+
}
99+
100+
err := r.Fetch(o)
101+
c.Assert(err, IsNil)
102+
err = r.Fetch(o)
103+
c.Assert(err, Equals, NoErrAlreadyUpToDate)
87104
}
88105

89106
func (s *RemoteSuite) TestHead(c *C) {

repository.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ import (
1212
)
1313

1414
var (
15-
ErrObjectNotFound = errors.New("object not found")
16-
ErrInvalidReference = errors.New("invalid reference, should be a tag or a branch")
15+
ErrObjectNotFound = errors.New("object not found")
16+
ErrInvalidReference = errors.New("invalid reference, should be a tag or a branch")
17+
ErrRepositoryNonEmpty = errors.New("repository non empty")
1718
)
1819

1920
// Repository giturl string, auth common.AuthMethod repository struct
@@ -94,6 +95,15 @@ func (r *Repository) DeleteRemote(name string) error {
9495

9596
// Clone clones a remote repository
9697
func (r *Repository) Clone(o *CloneOptions) error {
98+
empty, err := r.IsEmpty()
99+
if err != nil {
100+
return err
101+
}
102+
103+
if !empty {
104+
return ErrRepositoryNonEmpty
105+
}
106+
97107
if err := o.Validate(); err != nil {
98108
return err
99109
}
@@ -166,6 +176,15 @@ func (r *Repository) createReferences(ref *core.Reference) error {
166176
return r.s.ReferenceStorage().Set(head)
167177
}
168178

179+
// IsEmpty returns true if the repository is empty
180+
func (r *Repository) IsEmpty() (bool, error) {
181+
var count int
182+
return count == 0, r.Refs().ForEach(func(r *core.Reference) error {
183+
count++
184+
return nil
185+
})
186+
}
187+
169188
// Pull incorporates changes from a remote repository into the current branch
170189
func (r *Repository) Pull(o *PullOptions) error {
171190
if err := o.Validate(); err != nil {

repository_test.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,21 @@ func (s *RepositorySuite) TestClone(c *C) {
106106
c.Assert(branch.Hash().String(), Equals, "e8d3ffab552895c19b9fcf7aa264d277cde33881")
107107
}
108108

109+
func (s *RepositorySuite) TestCloneNonEmpty(c *C) {
110+
r := NewMemoryRepository()
111+
112+
head, err := r.Head()
113+
c.Assert(err, Equals, core.ErrReferenceNotFound)
114+
c.Assert(head, IsNil)
115+
116+
o := &CloneOptions{URL: RepositoryFixture}
117+
err = r.Clone(o)
118+
c.Assert(err, IsNil)
119+
120+
err = r.Clone(o)
121+
c.Assert(err, Equals, ErrRepositoryNonEmpty)
122+
}
123+
109124
func (s *RepositorySuite) TestCloneSingleBranchAndNonHEAD(c *C) {
110125
r := NewMemoryRepository()
111126

@@ -193,6 +208,21 @@ func (s *RepositorySuite) TestCloneDetachedHEAD(c *C) {
193208
c.Assert(head.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
194209
}
195210

211+
func (s *RepositorySuite) TestIsEmpty(c *C) {
212+
r := NewMemoryRepository()
213+
214+
empty, err := r.IsEmpty()
215+
c.Assert(err, IsNil)
216+
c.Assert(empty, Equals, true)
217+
218+
err = r.Clone(&CloneOptions{URL: RepositoryFixture})
219+
c.Assert(err, IsNil)
220+
221+
empty, err = r.IsEmpty()
222+
c.Assert(err, IsNil)
223+
c.Assert(empty, Equals, false)
224+
}
225+
196226
func (s *RepositorySuite) TestCommit(c *C) {
197227
r := NewMemoryRepository()
198228
err := r.Clone(&CloneOptions{
@@ -237,7 +267,7 @@ func (s *RepositorySuite) TestCommits(c *C) {
237267
c.Assert(commit.Type(), Equals, core.CommitObject)
238268
}
239269

240-
c.Assert(count, Equals, 8)
270+
c.Assert(count, Equals, 9)
241271
}
242272

243273
func (s *RepositorySuite) TestTag(c *C) {

0 commit comments

Comments
 (0)