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

Commit 524a28b

Browse files
smolamcuadros
authored andcommitted
storage: Add object type hint parameter to ObjectStorage.Get. (#69)
Some storage backends can optimize object lookup if they get the object type that is expected. So we the signature of the Get method is now Get(Hash, ObjectType). Added generic tests for storage backends.
1 parent 199a1bb commit 524a28b

File tree

17 files changed

+171
-140
lines changed

17 files changed

+171
-140
lines changed

commit_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func (s *SuiteCommit) SetUpSuite(c *C) {
2828

2929
func (s *SuiteCommit) TestDecodeNonCommit(c *C) {
3030
hash := core.NewHash("9a48f23120e880dfbe41f7c9b7b708e9ee62a492")
31-
blob, err := s.Repository.s.ObjectStorage().Get(hash)
31+
blob, err := s.Repository.s.ObjectStorage().Get(hash, core.AnyObject)
3232
c.Assert(err, IsNil)
3333

3434
commit := &Commit{}

core/object.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,22 @@ type Object interface {
3838
Writer() (ObjectWriter, error)
3939
}
4040

41-
// ObjectType internal object type's
41+
// ObjectType internal object type
42+
// Integer values from 0 to 7 map to those exposed by git.
43+
// AnyObject is used to represent any from 0 to 7.
4244
type ObjectType int8
4345

4446
const (
45-
InvalidObject ObjectType = 0
46-
CommitObject ObjectType = 1
47-
TreeObject ObjectType = 2
48-
BlobObject ObjectType = 3
49-
TagObject ObjectType = 4
47+
InvalidObject ObjectType = 0
48+
CommitObject ObjectType = 1
49+
TreeObject ObjectType = 2
50+
BlobObject ObjectType = 3
51+
TagObject ObjectType = 4
52+
// 5 reserved for future expansion
5053
OFSDeltaObject ObjectType = 6
5154
REFDeltaObject ObjectType = 7
55+
56+
AnyObject ObjectType = -127
5257
)
5358

5459
func (t ObjectType) String() string {
@@ -132,7 +137,7 @@ func (iter *ObjectLookupIter) Next() (Object, error) {
132137
return nil, io.EOF
133138
}
134139
hash := iter.series[iter.pos]
135-
obj, err := iter.storage.Get(hash)
140+
obj, err := iter.storage.Get(hash, AnyObject)
136141
if err == nil {
137142
iter.pos++
138143
}
@@ -146,7 +151,7 @@ func (iter *ObjectLookupIter) ForEach(cb func(Object) error) error {
146151
defer iter.Close()
147152

148153
for _, hash := range iter.series {
149-
obj, err := iter.storage.Get(hash)
154+
obj, err := iter.storage.Get(hash, AnyObject)
150155
if err != nil {
151156
return err
152157
}

core/storage.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,16 @@ var ErrStop = errors.New("stop iter")
99
type ObjectStorage interface {
1010
NewObject() Object
1111
Set(Object) (Hash, error)
12-
Get(Hash) (Object, error)
12+
// Get an object by hash with the given ObjectType.
13+
//
14+
// Implementors should return (nil, core.ErrObjectNotFound) if an object
15+
// doesn't exist with both the given hash and object type.
16+
//
17+
// Valid ObjectType values are CommitObject, BlobObject, TagObject, TreeObject
18+
// and AnyObject.
19+
//
20+
// If AnyObject is given, the object must be looked up regardless of its type.
21+
Get(Hash, ObjectType) (Object, error)
1322
Iter(ObjectType) (ObjectIter, error)
1423
}
1524

examples/object_storage/storage.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ func (o *AerospikeObjectStorage) Set(obj core.Object) (core.Hash, error) {
8686
return obj.Hash(), err
8787
}
8888

89-
func (o *AerospikeObjectStorage) Get(h core.Hash) (core.Object, error) {
90-
key, err := keyFromObject(h)
89+
func (o *AerospikeObjectStorage) Get(h core.Hash, t core.ObjectType) (core.Object, error) {
90+
key, err := keyFromObject(h, t)
9191
if err != nil {
9292
return nil, err
9393
}
@@ -113,8 +113,8 @@ func (o *AerospikeObjectStorage) Iter(t core.ObjectType) (core.ObjectIter, error
113113
return &AerospikeObjectIter{t, rs.Records}, nil
114114
}
115115

116-
func keyFromObject(h core.Hash) (*aerospike.Key, error) {
117-
return aerospike.NewKey("test", "objects", h.String())
116+
func keyFromObject(h core.Hash, t core.ObjectType) (*aerospike.Key, error) {
117+
return aerospike.NewKey("test", t.String(), h.String())
118118
}
119119

120120
type AerospikeObjectIter struct {

formats/packfile/decoder_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ func AssertObjects(c *C, s *memory.Storage, expects []string) {
104104

105105
c.Assert(len(expects), Equals, len(o.Objects))
106106
for _, exp := range expects {
107-
obt, err := o.Get(core.NewHash(exp))
107+
obt, err := o.Get(core.NewHash(exp), core.AnyObject)
108108
c.Assert(err, IsNil)
109109
c.Assert(obt.Hash().String(), Equals, exp)
110110
}

remote.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ func (r *Remote) getWantedReferences(spec []config.RefSpec) ([]*core.Reference,
123123
return nil
124124
}
125125

126-
_, err := r.s.ObjectStorage().Get(ref.Hash())
126+
_, err := r.s.ObjectStorage().Get(ref.Hash(), core.CommitObject)
127127
if err == core.ErrObjectNotFound {
128128
refs = append(refs, ref)
129129
return nil

repository.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ func (r *Repository) Pull(o *PullOptions) error {
226226

227227
// Commit return the commit with the given hash
228228
func (r *Repository) Commit(h core.Hash) (*Commit, error) {
229-
obj, err := r.s.ObjectStorage().Get(h)
229+
obj, err := r.s.ObjectStorage().Get(h, core.CommitObject)
230230
if err != nil {
231231
if err == core.ErrObjectNotFound {
232232
return nil, ErrObjectNotFound
@@ -250,7 +250,7 @@ func (r *Repository) Commits() (*CommitIter, error) {
250250

251251
// Tree return the tree with the given hash
252252
func (r *Repository) Tree(h core.Hash) (*Tree, error) {
253-
obj, err := r.s.ObjectStorage().Get(h)
253+
obj, err := r.s.ObjectStorage().Get(h, core.TreeObject)
254254
if err != nil {
255255
if err == core.ErrObjectNotFound {
256256
return nil, ErrObjectNotFound
@@ -264,7 +264,7 @@ func (r *Repository) Tree(h core.Hash) (*Tree, error) {
264264

265265
// Blob returns the blob with the given hash
266266
func (r *Repository) Blob(h core.Hash) (*Blob, error) {
267-
obj, err := r.s.ObjectStorage().Get(h)
267+
obj, err := r.s.ObjectStorage().Get(h, core.BlobObject)
268268
if err != nil {
269269
if err == core.ErrObjectNotFound {
270270
return nil, ErrObjectNotFound
@@ -278,7 +278,7 @@ func (r *Repository) Blob(h core.Hash) (*Blob, error) {
278278

279279
// Tag returns a tag with the given hash.
280280
func (r *Repository) Tag(h core.Hash) (*Tag, error) {
281-
obj, err := r.s.ObjectStorage().Get(h)
281+
obj, err := r.s.ObjectStorage().Get(h, core.TagObject)
282282
if err != nil {
283283
if err == core.ErrObjectNotFound {
284284
return nil, ErrObjectNotFound
@@ -302,8 +302,8 @@ func (r *Repository) Tags() (*TagIter, error) {
302302
}
303303

304304
// Object returns an object with the given hash.
305-
func (r *Repository) Object(h core.Hash) (Object, error) {
306-
obj, err := r.s.ObjectStorage().Get(h)
305+
func (r *Repository) Object(h core.Hash, t core.ObjectType) (Object, error) {
306+
obj, err := r.s.ObjectStorage().Get(h, t)
307307
if err != nil {
308308
if err == core.ErrObjectNotFound {
309309
return nil, ErrObjectNotFound

repository_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ func (s *RepositorySuite) TestObject(c *C) {
303303
com := fmt.Sprintf("subtest %d, tag %d", i, k)
304304
info := t.objs[k]
305305
hash := core.NewHash(info.Hash)
306-
obj, err := r.Object(hash)
306+
obj, err := r.Object(hash, core.AnyObject)
307307
c.Assert(err, IsNil, Commentf(com))
308308
c.Assert(obj.Type(), Equals, info.Kind, Commentf(com))
309309
c.Assert(obj.ID(), Equals, hash, Commentf(com))

storage/filesystem/object.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func (s *ObjectStorage) Set(core.Object) (core.Hash, error) {
3838

3939
// Get returns the object with the given hash, by searching for it in
4040
// the packfile.
41-
func (s *ObjectStorage) Get(h core.Hash) (core.Object, error) {
41+
func (s *ObjectStorage) Get(h core.Hash, t core.ObjectType) (core.Object, error) {
4242
offset, err := s.index.Get(h)
4343
if err != nil {
4444
return nil, err
@@ -71,7 +71,14 @@ func (s *ObjectStorage) Get(h core.Hash) (core.Object, error) {
7171
p := packfile.NewParser(r)
7272

7373
obj := s.NewObject()
74-
return obj, p.FillObject(obj)
74+
err = p.FillObject(obj)
75+
if err != nil {
76+
return nil, err
77+
}
78+
if core.AnyObject != t && obj.Type() != t {
79+
return nil, core.ErrObjectNotFound
80+
}
81+
return obj, nil
7582
}
7683

7784
// Iter returns an iterator for all the objects in the packfile with the
@@ -80,11 +87,11 @@ func (s *ObjectStorage) Iter(t core.ObjectType) (core.ObjectIter, error) {
8087
var objects []core.Object
8188

8289
for hash := range s.index {
83-
object, err := s.Get(hash)
90+
object, err := s.Get(hash, core.AnyObject)
8491
if err != nil {
8592
return nil, err
8693
}
87-
if object.Type() == t {
94+
if t == core.AnyObject || object.Type() == t {
8895
objects = append(objects, object)
8996
}
9097
}

storage/filesystem/object_test.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,11 @@ func (s *FsSuite) TearDownSuite(c *C) {
6464

6565
func (s *FsSuite) TestHashNotFound(c *C) {
6666
sto := s.newObjectStorage(c, "binary-relations")
67-
68-
_, err := sto.Get(core.ZeroHash)
69-
c.Assert(err, Equals, core.ErrObjectNotFound)
67+
types := []core.ObjectType{core.AnyObject, core.TagObject, core.CommitObject, core.BlobObject, core.TreeObject}
68+
for t := range types {
69+
_, err := sto.Get(core.ZeroHash, core.ObjectType(t))
70+
c.Assert(err, Equals, core.ErrObjectNotFound)
71+
}
7072
}
7173

7274
func (s *FsSuite) newObjectStorage(c *C, fixtureName string) core.ObjectStorage {
@@ -156,7 +158,7 @@ func equalsStorages(a, b core.ObjectStorage) (bool, string, error) {
156158
break
157159
}
158160

159-
bo, err := b.Get(ao.Hash())
161+
bo, err := b.Get(ao.Hash(), core.AnyObject)
160162
if err != nil {
161163
return false, "", fmt.Errorf("getting object with hash %s: %s",
162164
ao.Hash(), err)

storage/memory/storage.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,19 +130,20 @@ func (o *ObjectStorage) Set(obj core.Object) (core.Hash, error) {
130130
}
131131

132132
// Get returns a object with the given hash
133-
func (o *ObjectStorage) Get(h core.Hash) (core.Object, error) {
133+
func (o *ObjectStorage) Get(h core.Hash, t core.ObjectType) (core.Object, error) {
134134
obj, ok := o.Objects[h]
135-
if !ok {
135+
if !ok || (core.AnyObject != t && obj.Type() != t) {
136136
return nil, core.ErrObjectNotFound
137137
}
138-
139138
return obj, nil
140139
}
141140

142141
// Iter returns a core.ObjectIter for the given core.ObjectTybe
143142
func (o *ObjectStorage) Iter(t core.ObjectType) (core.ObjectIter, error) {
144143
var series []core.Object
145144
switch t {
145+
case core.AnyObject:
146+
series = flattenObjectMap(o.Objects)
146147
case core.CommitObject:
147148
series = flattenObjectMap(o.Commits)
148149
case core.TreeObject:

storage/memory/storage_test.go

Lines changed: 7 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,20 @@ import (
66

77
. "gopkg.in/check.v1"
88
"gopkg.in/src-d/go-git.v4/core"
9+
. "gopkg.in/src-d/go-git.v4/storage/test"
910
)
1011

1112
func Test(t *testing.T) { TestingT(t) }
1213

13-
type StorageSuite struct{}
14+
type StorageSuite struct { }
1415

1516
var _ = Suite(&StorageSuite{})
1617

18+
func (s *StorageSuite) TestObjectStorage(c *C) {
19+
storage := NewStorage()
20+
RunObjectStorageSuite(c, storage.ObjectStorage())
21+
}
22+
1723
func (s *StorageSuite) TestStorageObjectStorage(c *C) {
1824
storage := NewStorage()
1925
o := storage.ObjectStorage()
@@ -30,102 +36,6 @@ func (s *StorageSuite) TestStorageReferenceStorage(c *C) {
3036
c.Assert(o == e, Equals, true)
3137
}
3238

33-
func (s *StorageSuite) TestObjectStorageSetAndGet(c *C) {
34-
storage := NewStorage()
35-
os := storage.ObjectStorage()
36-
37-
commit := &core.MemoryObject{}
38-
commit.SetType(core.CommitObject)
39-
40-
h, err := os.Set(commit)
41-
c.Assert(err, IsNil)
42-
c.Assert(h.String(), Equals, "dcf5b16e76cce7425d0beaef62d79a7d10fce1f5")
43-
44-
e, err := os.Get(h)
45-
c.Assert(commit == e, Equals, true)
46-
47-
tree := &core.MemoryObject{}
48-
tree.SetType(core.TreeObject)
49-
50-
h, err = os.Set(tree)
51-
c.Assert(err, IsNil)
52-
c.Assert(h.String(), Equals, "4b825dc642cb6eb9a060e54bf8d69288fbee4904")
53-
54-
e, err = os.Get(h)
55-
c.Assert(tree == e, Equals, true)
56-
57-
blob := &core.MemoryObject{}
58-
blob.SetType(core.BlobObject)
59-
60-
h, err = os.Set(blob)
61-
c.Assert(err, IsNil)
62-
c.Assert(h.String(), Equals, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391")
63-
64-
e, err = os.Get(h)
65-
c.Assert(blob == e, Equals, true)
66-
67-
tag := &core.MemoryObject{}
68-
tag.SetType(core.TagObject)
69-
70-
h, err = os.Set(tag)
71-
c.Assert(err, IsNil)
72-
c.Assert(h.String(), Equals, "d994c6bb648123a17e8f70a966857c546b2a6f94")
73-
74-
e, err = os.Get(h)
75-
c.Assert(tag == e, Equals, true)
76-
}
77-
78-
func (s *StorageSuite) TestObjectStorageIter(c *C) {
79-
commit := &core.MemoryObject{}
80-
commit.SetType(core.CommitObject)
81-
tree := &core.MemoryObject{}
82-
tree.SetType(core.TreeObject)
83-
blob := &core.MemoryObject{}
84-
blob.SetType(core.BlobObject)
85-
tag := &core.MemoryObject{}
86-
tag.SetType(core.TagObject)
87-
88-
storage := NewStorage()
89-
os := storage.ObjectStorage()
90-
91-
os.Set(commit)
92-
os.Set(tree)
93-
os.Set(blob)
94-
os.Set(tag)
95-
96-
i, err := os.Iter(core.CommitObject)
97-
c.Assert(err, IsNil)
98-
99-
e, err := i.Next()
100-
c.Assert(err, IsNil)
101-
c.Assert(commit == e, Equals, true)
102-
103-
i, err = os.Iter(core.TreeObject)
104-
c.Assert(err, IsNil)
105-
106-
e, err = i.Next()
107-
c.Assert(err, IsNil)
108-
c.Assert(tree == e, Equals, true)
109-
110-
i, err = os.Iter(core.BlobObject)
111-
c.Assert(err, IsNil)
112-
113-
e, err = i.Next()
114-
c.Assert(err, IsNil)
115-
c.Assert(blob == e, Equals, true)
116-
117-
i, err = os.Iter(core.TagObject)
118-
c.Assert(err, IsNil)
119-
120-
e, err = i.Next()
121-
c.Assert(err, IsNil)
122-
c.Assert(tag == e, Equals, true)
123-
124-
e, err = i.Next()
125-
c.Assert(e, IsNil)
126-
c.Assert(err, Equals, io.EOF)
127-
}
128-
12939
func (s *StorageSuite) TestReferenceStorageSetAndGet(c *C) {
13040
storage := NewStorage()
13141
rs := storage.ReferenceStorage()

0 commit comments

Comments
 (0)