diff options
-rw-r--r-- | remote.go | 19 | ||||
-rw-r--r-- | remote_test.go | 52 | ||||
-rw-r--r-- | repository_test.go | 63 | ||||
-rw-r--r-- | storage/filesystem/internal/dotgit/dotgit.go | 12 | ||||
-rw-r--r-- | storage/filesystem/internal/dotgit/dotgit_test.go | 15 | ||||
-rw-r--r-- | storage/filesystem/shallow.go | 2 |
6 files changed, 158 insertions, 5 deletions
@@ -976,9 +976,24 @@ func pushHashes( } func (r *Remote) updateShallow(o *FetchOptions, resp *packp.UploadPackResponse) error { - if o.Depth == 0 { + if o.Depth == 0 || len(resp.Shallows) == 0 { return nil } - return r.s.SetShallow(resp.Shallows) + shallows, err := r.s.Shallow() + if err != nil { + return err + } + +outer: + for _, s := range resp.Shallows { + for _, oldS := range shallows { + if s == oldS { + continue outer + } + } + shallows = append(shallows, s) + } + + return r.s.SetShallow(shallows) } diff --git a/remote_test.go b/remote_test.go index e586e7a..82ec1fc 100644 --- a/remote_test.go +++ b/remote_test.go @@ -9,6 +9,7 @@ import ( "gopkg.in/src-d/go-git.v4/config" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/protocol/packp" "gopkg.in/src-d/go-git.v4/plumbing/storer" "gopkg.in/src-d/go-git.v4/storage" "gopkg.in/src-d/go-git.v4/storage/filesystem" @@ -741,3 +742,54 @@ func (s *RemoteSuite) TestList(c *C) { c.Assert(found, Equals, true) } } + +func (s *RemoteSuite) TestUpdateShallows(c *C) { + hashes := []plumbing.Hash{ + plumbing.NewHash("0000000000000000000000000000000000000001"), + plumbing.NewHash("0000000000000000000000000000000000000002"), + plumbing.NewHash("0000000000000000000000000000000000000003"), + plumbing.NewHash("0000000000000000000000000000000000000004"), + plumbing.NewHash("0000000000000000000000000000000000000005"), + plumbing.NewHash("0000000000000000000000000000000000000006"), + } + + tests := []struct { + hashes []plumbing.Hash + result []plumbing.Hash + }{ + // add to empty shallows + {hashes[0:2], hashes[0:2]}, + // add new hashes + {hashes[2:4], hashes[0:4]}, + // add some hashes already in shallow list + {hashes[2:6], hashes[0:6]}, + // add all hashes + {hashes[0:6], hashes[0:6]}, + // add empty list + {nil, hashes[0:6]}, + } + + remote := newRemote(memory.NewStorage(), &config.RemoteConfig{ + Name: DefaultRemoteName, + }) + + shallows, err := remote.s.Shallow() + c.Assert(err, IsNil) + c.Assert(len(shallows), Equals, 0) + + resp := new(packp.UploadPackResponse) + o := &FetchOptions{ + Depth: 1, + } + + for _, t := range tests { + resp.Shallows = t.hashes + err = remote.updateShallow(o, resp) + c.Assert(err, IsNil) + + shallow, err := remote.s.Shallow() + c.Assert(err, IsNil) + c.Assert(len(shallow), Equals, len(t.result)) + c.Assert(shallow, DeepEquals, t.result) + } +} diff --git a/repository_test.go b/repository_test.go index 3e94db9..b78fbb7 100644 --- a/repository_test.go +++ b/repository_test.go @@ -1625,3 +1625,66 @@ func executeOnPath(path, cmd string) error { return c.Run() } + +func (s *RepositorySuite) TestBrokenMultipleShallowFetch(c *C) { + r, _ := Init(memory.NewStorage(), nil) + _, err := r.CreateRemote(&config.RemoteConfig{ + Name: DefaultRemoteName, + URLs: []string{s.GetBasicLocalRepositoryURL()}, + }) + c.Assert(err, IsNil) + + c.Assert(r.Fetch(&FetchOptions{ + Depth: 2, + RefSpecs: []config.RefSpec{config.RefSpec("refs/heads/master:refs/heads/master")}, + }), IsNil) + + shallows, err := r.Storer.Shallow() + c.Assert(err, IsNil) + c.Assert(len(shallows), Equals, 1) + + ref, err := r.Reference("refs/heads/master", true) + c.Assert(err, IsNil) + cobj, err := r.CommitObject(ref.Hash()) + c.Assert(err, IsNil) + c.Assert(cobj, NotNil) + err = object.NewCommitPreorderIter(cobj, nil, nil).ForEach(func(c *object.Commit) error { + for _, ph := range c.ParentHashes { + for _, h := range shallows { + if ph == h { + return storer.ErrStop + } + } + } + + return nil + }) + c.Assert(err, IsNil) + + c.Assert(r.Fetch(&FetchOptions{ + Depth: 5, + RefSpecs: []config.RefSpec{config.RefSpec("refs/heads/*:refs/heads/*")}, + }), IsNil) + + shallows, err = r.Storer.Shallow() + c.Assert(err, IsNil) + c.Assert(len(shallows), Equals, 3) + + ref, err = r.Reference("refs/heads/master", true) + c.Assert(err, IsNil) + cobj, err = r.CommitObject(ref.Hash()) + c.Assert(err, IsNil) + c.Assert(cobj, NotNil) + err = object.NewCommitPreorderIter(cobj, nil, nil).ForEach(func(c *object.Commit) error { + for _, ph := range c.ParentHashes { + for _, h := range shallows { + if ph == h { + return storer.ErrStop + } + } + } + + return nil + }) + c.Assert(err, IsNil) +} diff --git a/storage/filesystem/internal/dotgit/dotgit.go b/storage/filesystem/internal/dotgit/dotgit.go index 6f0f1a5..52b621c 100644 --- a/storage/filesystem/internal/dotgit/dotgit.go +++ b/storage/filesystem/internal/dotgit/dotgit.go @@ -162,8 +162,11 @@ func (d *DotGit) ObjectPacks() ([]plumbing.Hash, error) { n := f.Name() h := plumbing.NewHash(n[5 : len(n)-5]) //pack-(hash).pack + if h.IsZero() { + // Ignore files with badly-formatted names. + continue + } packs = append(packs, h) - } return packs, nil @@ -255,7 +258,12 @@ func (d *DotGit) ForEachObjectHash(fun func(plumbing.Hash) error) error { } for _, o := range d { - err = fun(plumbing.NewHash(base + o.Name())) + h := plumbing.NewHash(base + o.Name()) + if h.IsZero() { + // Ignore files with badly-formatted names. + continue + } + err = fun(h) if err != nil { return err } diff --git a/storage/filesystem/internal/dotgit/dotgit_test.go b/storage/filesystem/internal/dotgit/dotgit_test.go index 2c43295..7733eef 100644 --- a/storage/filesystem/internal/dotgit/dotgit_test.go +++ b/storage/filesystem/internal/dotgit/dotgit_test.go @@ -151,6 +151,7 @@ func (s *SuiteDotGit) TestRefsFromReferenceFile(c *C) { } func BenchmarkRefMultipleTimes(b *testing.B) { + fixtures.Init() fs := fixtures.Basic().ByTag(".git").One().DotGit() refname := plumbing.ReferenceName("refs/remotes/origin/branch") @@ -418,7 +419,7 @@ func findReference(refs []*plumbing.Reference, name string) *plumbing.Reference return nil } -func (s *SuiteDotGit) TestObjectsPack(c *C) { +func (s *SuiteDotGit) TestObjectPacks(c *C) { f := fixtures.Basic().ByTag(".git").One() fs := f.DotGit() dir := New(fs) @@ -427,6 +428,18 @@ func (s *SuiteDotGit) TestObjectsPack(c *C) { c.Assert(err, IsNil) c.Assert(hashes, HasLen, 1) c.Assert(hashes[0], Equals, f.PackfileHash) + + // Make sure that a random file in the pack directory doesn't + // break everything. + badFile, err := fs.Create("objects/pack/OOPS_THIS_IS_NOT_RIGHT.pack") + c.Assert(err, IsNil) + err = badFile.Close() + c.Assert(err, IsNil) + + hashes2, err := dir.ObjectPacks() + c.Assert(err, IsNil) + c.Assert(hashes2, HasLen, 1) + c.Assert(hashes[0], Equals, hashes2[0]) } func (s *SuiteDotGit) TestObjectPack(c *C) { diff --git a/storage/filesystem/shallow.go b/storage/filesystem/shallow.go index 4b2e2dc..173767c 100644 --- a/storage/filesystem/shallow.go +++ b/storage/filesystem/shallow.go @@ -41,6 +41,8 @@ func (s *ShallowStorage) Shallow() ([]plumbing.Hash, error) { return nil, err } + defer ioutil.CheckClose(f, &err) + var hash []plumbing.Hash scn := bufio.NewScanner(f) |