aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing/object/blob.go
diff options
context:
space:
mode:
Diffstat (limited to 'plumbing/object/blob.go')
-rw-r--r--plumbing/object/blob.go135
1 files changed, 135 insertions, 0 deletions
diff --git a/plumbing/object/blob.go b/plumbing/object/blob.go
new file mode 100644
index 0000000..b0cac41
--- /dev/null
+++ b/plumbing/object/blob.go
@@ -0,0 +1,135 @@
+package object
+
+import (
+ "io"
+
+ "gopkg.in/src-d/go-git.v4/plumbing"
+ "gopkg.in/src-d/go-git.v4/plumbing/storer"
+ "gopkg.in/src-d/go-git.v4/utils/ioutil"
+)
+
+// Blob is used to store file data - it is generally a file.
+type Blob struct {
+ Hash plumbing.Hash
+ Size int64
+
+ obj plumbing.EncodedObject
+}
+
+// GetBlob gets a blob from an object storer and decodes it.
+func GetBlob(s storer.EncodedObjectStorer, h plumbing.Hash) (*Blob, error) {
+ o, err := s.EncodedObject(plumbing.BlobObject, h)
+ if err != nil {
+ return nil, err
+ }
+
+ return DecodeBlob(o)
+}
+
+func DecodeBlob(o plumbing.EncodedObject) (*Blob, error) {
+ b := &Blob{}
+ if err := b.Decode(o); err != nil {
+ return nil, err
+ }
+
+ return b, nil
+}
+
+// ID returns the object ID of the blob. The returned value will always match
+// the current value of Blob.Hash.
+//
+// ID is present to fulfill the Object interface.
+func (b *Blob) ID() plumbing.Hash {
+ return b.Hash
+}
+
+// Type returns the type of object. It always returns plumbing.BlobObject.
+//
+// Type is present to fulfill the Object interface.
+func (b *Blob) Type() plumbing.ObjectType {
+ return plumbing.BlobObject
+}
+
+// Decode transforms a plumbing.EncodedObject into a Blob struct.
+func (b *Blob) Decode(o plumbing.EncodedObject) error {
+ if o.Type() != plumbing.BlobObject {
+ return ErrUnsupportedObject
+ }
+
+ b.Hash = o.Hash()
+ b.Size = o.Size()
+ b.obj = o
+
+ return nil
+}
+
+// Encode transforms a Blob into a plumbing.EncodedObject.
+func (b *Blob) Encode(o plumbing.EncodedObject) error {
+ w, err := o.Writer()
+ if err != nil {
+ return err
+ }
+ defer ioutil.CheckClose(w, &err)
+ r, err := b.Reader()
+ if err != nil {
+ return err
+ }
+ defer ioutil.CheckClose(r, &err)
+ _, err = io.Copy(w, r)
+ o.SetType(plumbing.BlobObject)
+ return err
+}
+
+// Reader returns a reader allow the access to the content of the blob
+func (b *Blob) Reader() (io.ReadCloser, error) {
+ return b.obj.Reader()
+}
+
+// BlobIter provides an iterator for a set of blobs.
+type BlobIter struct {
+ storer.EncodedObjectIter
+ s storer.EncodedObjectStorer
+}
+
+// NewBlobIter returns a CommitIter for the given repository and underlying
+// object iterator.
+//
+// The returned BlobIter will automatically skip over non-blob objects.
+func NewBlobIter(s storer.EncodedObjectStorer, iter storer.EncodedObjectIter) *BlobIter {
+ return &BlobIter{iter, s}
+}
+
+// Next moves the iterator to the next blob and returns a pointer to it. If it
+// has reached the end of the set it will return io.EOF.
+func (iter *BlobIter) Next() (*Blob, error) {
+ for {
+ obj, err := iter.EncodedObjectIter.Next()
+ if err != nil {
+ return nil, err
+ }
+
+ if obj.Type() != plumbing.BlobObject {
+ continue
+ }
+
+ return DecodeBlob(obj)
+ }
+}
+
+// ForEach call the cb function for each blob contained on this iter until
+// an error happens or the end of the iter is reached. If ErrStop is sent
+// the iteration is stop but no error is returned. The iterator is closed.
+func (iter *BlobIter) ForEach(cb func(*Blob) error) error {
+ return iter.EncodedObjectIter.ForEach(func(obj plumbing.EncodedObject) error {
+ if obj.Type() != plumbing.BlobObject {
+ return nil
+ }
+
+ b, err := DecodeBlob(obj)
+ if err != nil {
+ return err
+ }
+
+ return cb(b)
+ })
+}