aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/object.go113
1 files changed, 113 insertions, 0 deletions
diff --git a/core/object.go b/core/object.go
index 1034ab3..62cb469 100644
--- a/core/object.go
+++ b/core/object.go
@@ -2,9 +2,14 @@ package core
import (
"bytes"
+ "errors"
"io"
)
+var (
+ ObjectNotFoundErr = errors.New("object not found")
+)
+
// Object is a generic representation of any git object
type Object interface {
Type() ObjectType
@@ -21,6 +26,7 @@ type ObjectStorage interface {
New() Object
Set(Object) Hash
Get(Hash) (Object, bool)
+ Iter(ObjectType) ObjectIter
}
// ObjectType internal object type's
@@ -58,6 +64,92 @@ func (t ObjectType) Bytes() []byte {
return []byte(t.String())
}
+// ObjectIter is a generic closable interface for iterating over objects.
+type ObjectIter interface {
+ Next() (Object, error)
+ Close()
+}
+
+// ObjectLookupIter implements ObjectIter. It iterates over a series of object
+// hashes and yields their associated objects by retrieving each one from
+// object storage. The retrievals are lazy and only occur when the iterator
+// moves forward with a call to Next().
+//
+// The ObjectLookupIter must be closed with a call to Close() when it is no
+// longer needed.
+type ObjectLookupIter struct {
+ storage ObjectStorage
+ series []Hash
+ pos int
+}
+
+// NewObjectLookupIter returns an object iterator given an object storage and
+// a slice of object hashes.
+func NewObjectLookupIter(storage ObjectStorage, series []Hash) *ObjectLookupIter {
+ return &ObjectLookupIter{
+ storage: storage,
+ series: series,
+ }
+}
+
+// Next returns the next object from the iterator. If the iterator has reached
+// the end it will return io.EOF as an error. If the object can't be found in
+// the object storage, it will return ObjectNotFoundErr as an error. If the
+// object is retreieved successfully error will be nil.
+func (iter *ObjectLookupIter) Next() (Object, error) {
+ if iter.pos >= len(iter.series) {
+ return nil, io.EOF
+ }
+ hash := iter.series[iter.pos]
+ obj, ok := iter.storage.Get(hash)
+ if !ok {
+ // FIXME: Consider making ObjectStorage.Get return an actual error that we
+ // could pass back here.
+ return nil, ObjectNotFoundErr
+ }
+ iter.pos++
+ return obj, nil
+}
+
+// Close releases any resources used by the iterator.
+func (iter *ObjectLookupIter) Close() {
+ iter.pos = len(iter.series)
+}
+
+// ObjectSliceIter implements ObjectIter. It iterates over a series of objects
+// stored in a slice and yields each one in turn when Next() is called.
+//
+// The ObjectSliceIter must be closed with a call to Close() when it is no
+// longer needed.
+type ObjectSliceIter struct {
+ series []Object
+ pos int
+}
+
+// NewObjectSliceIter returns an object iterator for the given slice of objects.
+func NewObjectSliceIter(series []Object) *ObjectSliceIter {
+ return &ObjectSliceIter{
+ series: series,
+ }
+}
+
+// Next returns the next object from the iterator. If the iterator has reached
+// the end it will return io.EOF as an error. If the object is retreieved
+// successfully error will be nil.
+func (iter *ObjectSliceIter) Next() (Object, error) {
+ if iter.pos >= len(iter.series) {
+ return nil, io.EOF
+ }
+ obj := iter.series[iter.pos]
+ iter.pos++
+ return obj, nil
+}
+
+// Close releases any resources used by the iterator.
+func (iter *ObjectSliceIter) Close() {
+ iter.pos = len(iter.series)
+}
+
type RAWObject struct {
b []byte
t ObjectType
@@ -117,3 +209,24 @@ func (o *RAWObjectStorage) Get(h Hash) (Object, bool) {
return obj, ok
}
+
+func (o *RAWObjectStorage) Iter(t ObjectType) ObjectIter {
+ var series []Object
+ switch t {
+ case CommitObject:
+ series = flattenObjectMap(o.Commits)
+ case TreeObject:
+ series = flattenObjectMap(o.Trees)
+ case BlobObject:
+ series = flattenObjectMap(o.Blobs)
+ }
+ return NewObjectSliceIter(series)
+}
+
+func flattenObjectMap(m map[Hash]Object) []Object {
+ objects := make([]Object, 0, len(m))
+ for _, obj := range m {
+ objects = append(objects, obj)
+ }
+ return objects
+}