diff options
-rw-r--r-- | storage/filesystem/object.go | 10 | ||||
-rw-r--r-- | storage/filesystem/object_test.go | 15 |
2 files changed, 25 insertions, 0 deletions
diff --git a/storage/filesystem/object.go b/storage/filesystem/object.go index 21667fa..846a7b8 100644 --- a/storage/filesystem/object.go +++ b/storage/filesystem/object.go @@ -537,14 +537,21 @@ func (s *ObjectStorage) findObjectInPackfile(h plumbing.Hash) (plumbing.Hash, pl return plumbing.ZeroHash, plumbing.ZeroHash, -1 } +// HashesWithPrefix returns all objects with a hash that starts with a prefix by searching for +// them in the packfile and the git object directories. func (s *ObjectStorage) HashesWithPrefix(prefix []byte) ([]plumbing.Hash, error) { hashes, err := s.dir.ObjectsWithPrefix(prefix) if err != nil { return nil, err } + seen := hashListAsMap(hashes) + // TODO: This could be faster with some idxfile changes, // or diving into the packfile. + if err := s.requireIndex(); err != nil { + return nil, err + } for _, index := range s.index { ei, err := index.Entries() if err != nil { @@ -558,6 +565,9 @@ func (s *ObjectStorage) HashesWithPrefix(prefix []byte) ([]plumbing.Hash, error) return nil, err } if bytes.HasPrefix(e.Hash[:], prefix) { + if _, ok := seen[e.Hash]; ok { + continue + } hashes = append(hashes, e.Hash) } } diff --git a/storage/filesystem/object_test.go b/storage/filesystem/object_test.go index 19a7914..b5f137f 100644 --- a/storage/filesystem/object_test.go +++ b/storage/filesystem/object_test.go @@ -406,6 +406,21 @@ func (s *FsSuite) TestHashesWithPrefix(c *C) { c.Assert(hashes[0].String(), Equals, "f3dfe29d268303fc6e1bbce268605fc99573406e") } +func (s *FsSuite) TestHashesWithPrefixFromPackfile(c *C) { + // Same setup as TestGetFromPackfile + fixtures.Basic().ByTag(".git").Test(c, func(f *fixtures.Fixture) { + fs := f.DotGit() + o := NewObjectStorage(dotgit.New(fs), cache.NewObjectLRUDefault()) + + expected := plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5") + // Only pass the first 8 bytes + hashes, err := o.HashesWithPrefix(expected[:8]) + c.Assert(err, IsNil) + c.Assert(hashes, HasLen, 1) + c.Assert(hashes[0], Equals, expected) + }) +} + func BenchmarkPackfileIter(b *testing.B) { defer fixtures.Clean() |