|
- 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 arbitrary data - it is generally a file.
- type Blob struct {
- // Hash of the blob.
- Hash plumbing.Hash
- // Size of the (uncompressed) blob.
- 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)
- }
-
- // DecodeObject decodes an encoded object into a *Blob.
- 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) (err error) {
- o.SetType(plumbing.BlobObject)
-
- 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)
- 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 takes a storer.EncodedObjectStorer and a
- // storer.EncodedObjectIter and returns a *BlobIter that iterates over all
- // blobs contained in the storer.EncodedObjectIter.
- //
- // Any non-blob object returned by the storer.EncodedObjectIter is skipped.
- 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
- // there are no more blobs, it returns 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)
- })
- }
|