|
- package storer
-
- import (
- "errors"
- "io"
- "time"
-
- "gopkg.in/src-d/go-git.v4/plumbing"
- )
-
- var (
- //ErrStop is used to stop a ForEach function in an Iter
- ErrStop = errors.New("stop iter")
- )
-
- // EncodedObjectStorer generic storage of objects
- type EncodedObjectStorer interface {
- // NewEncodedObject returns a new plumbing.EncodedObject, the real type
- // of the object can be a custom implementation or the default one,
- // plumbing.MemoryObject.
- NewEncodedObject() plumbing.EncodedObject
- // SetEncodedObject saves an object into the storage, the object should
- // be create with the NewEncodedObject, method, and file if the type is
- // not supported.
- SetEncodedObject(plumbing.EncodedObject) (plumbing.Hash, error)
- // EncodedObject gets an object by hash with the given
- // plumbing.ObjectType. Implementors should return
- // (nil, plumbing.ErrObjectNotFound) if an object doesn't exist with
- // both the given hash and object type.
- //
- // Valid plumbing.ObjectType values are CommitObject, BlobObject, TagObject,
- // TreeObject and AnyObject. If plumbing.AnyObject is given, the object must
- // be looked up regardless of its type.
- EncodedObject(plumbing.ObjectType, plumbing.Hash) (plumbing.EncodedObject, error)
- // IterObjects returns a custom EncodedObjectStorer over all the object
- // on the storage.
- //
- // Valid plumbing.ObjectType values are CommitObject, BlobObject, TagObject,
- IterEncodedObjects(plumbing.ObjectType) (EncodedObjectIter, error)
- // HasEncodedObject returns ErrObjNotFound if the object doesn't
- // exist. If the object does exist, it returns nil.
- HasEncodedObject(plumbing.Hash) error
- // EncodedObjectSize returns the plaintext size of the encoded object.
- EncodedObjectSize(plumbing.Hash) (int64, error)
- }
-
- // DeltaObjectStorer is an EncodedObjectStorer that can return delta
- // objects.
- type DeltaObjectStorer interface {
- // DeltaObject is the same as EncodedObject but without resolving deltas.
- // Deltas will be returned as plumbing.DeltaObject instances.
- DeltaObject(plumbing.ObjectType, plumbing.Hash) (plumbing.EncodedObject, error)
- }
-
- // Transactioner is a optional method for ObjectStorer, it enable transaction
- // base write and read operations in the storage
- type Transactioner interface {
- // Begin starts a transaction.
- Begin() Transaction
- }
-
- // LooseObjectStorer is an optional interface for managing "loose"
- // objects, i.e. those not in packfiles.
- type LooseObjectStorer interface {
- // ForEachObjectHash iterates over all the (loose) object hashes
- // in the repository without necessarily having to read those objects.
- // Objects only inside pack files may be omitted.
- // If ErrStop is sent the iteration is stop but no error is returned.
- ForEachObjectHash(func(plumbing.Hash) error) error
- // LooseObjectTime looks up the (m)time associated with the
- // loose object (that is not in a pack file). Some
- // implementations (e.g. without loose objects)
- // always return an error.
- LooseObjectTime(plumbing.Hash) (time.Time, error)
- // DeleteLooseObject deletes a loose object if it exists.
- DeleteLooseObject(plumbing.Hash) error
- }
-
- // PackedObjectStorer is an optional interface for managing objects in
- // packfiles.
- type PackedObjectStorer interface {
- // ObjectPacks returns hashes of object packs if the underlying
- // implementation has pack files.
- ObjectPacks() ([]plumbing.Hash, error)
- // DeleteOldObjectPackAndIndex deletes an object pack and the corresponding index file if they exist.
- // Deletion is only performed if the pack is older than the supplied time (or the time is zero).
- DeleteOldObjectPackAndIndex(plumbing.Hash, time.Time) error
- }
-
- // PackfileWriter is a optional method for ObjectStorer, it enable direct write
- // of packfile to the storage
- type PackfileWriter interface {
- // PackfileWriter returns a writer for writing a packfile to the storage
- //
- // If the Storer not implements PackfileWriter the objects should be written
- // using the Set method.
- PackfileWriter() (io.WriteCloser, error)
- }
-
- // EncodedObjectIter is a generic closable interface for iterating over objects.
- type EncodedObjectIter interface {
- Next() (plumbing.EncodedObject, error)
- ForEach(func(plumbing.EncodedObject) error) error
- Close()
- }
-
- // Transaction is an in-progress storage transaction. A transaction must end
- // with a call to Commit or Rollback.
- type Transaction interface {
- SetEncodedObject(plumbing.EncodedObject) (plumbing.Hash, error)
- EncodedObject(plumbing.ObjectType, plumbing.Hash) (plumbing.EncodedObject, error)
- Commit() error
- Rollback() error
- }
-
- // EncodedObjectLookupIter implements EncodedObjectIter. 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 EncodedObjectLookupIter must be closed with a call to Close() when it is
- // no longer needed.
- type EncodedObjectLookupIter struct {
- storage EncodedObjectStorer
- series []plumbing.Hash
- t plumbing.ObjectType
- pos int
- }
-
- // NewEncodedObjectLookupIter returns an object iterator given an object storage
- // and a slice of object hashes.
- func NewEncodedObjectLookupIter(
- storage EncodedObjectStorer, t plumbing.ObjectType, series []plumbing.Hash) *EncodedObjectLookupIter {
- return &EncodedObjectLookupIter{
- storage: storage,
- series: series,
- t: t,
- }
- }
-
- // 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 plumbing.ErrObjectNotFound as an error.
- // If the object is retreieved successfully error will be nil.
- func (iter *EncodedObjectLookupIter) Next() (plumbing.EncodedObject, error) {
- if iter.pos >= len(iter.series) {
- return nil, io.EOF
- }
-
- hash := iter.series[iter.pos]
- obj, err := iter.storage.EncodedObject(iter.t, hash)
- if err == nil {
- iter.pos++
- }
-
- return obj, err
- }
-
- // ForEach call the cb function for each object 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 *EncodedObjectLookupIter) ForEach(cb func(plumbing.EncodedObject) error) error {
- return ForEachIterator(iter, cb)
- }
-
- // Close releases any resources used by the iterator.
- func (iter *EncodedObjectLookupIter) Close() {
- iter.pos = len(iter.series)
- }
-
- // EncodedObjectSliceIter implements EncodedObjectIter. It iterates over a
- // series of objects stored in a slice and yields each one in turn when Next()
- // is called.
- //
- // The EncodedObjectSliceIter must be closed with a call to Close() when it is
- // no longer needed.
- type EncodedObjectSliceIter struct {
- series []plumbing.EncodedObject
- }
-
- // NewEncodedObjectSliceIter returns an object iterator for the given slice of
- // objects.
- func NewEncodedObjectSliceIter(series []plumbing.EncodedObject) *EncodedObjectSliceIter {
- return &EncodedObjectSliceIter{
- 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 *EncodedObjectSliceIter) Next() (plumbing.EncodedObject, error) {
- if len(iter.series) == 0 {
- return nil, io.EOF
- }
-
- obj := iter.series[0]
- iter.series = iter.series[1:]
-
- return obj, nil
- }
-
- // ForEach call the cb function for each object 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 *EncodedObjectSliceIter) ForEach(cb func(plumbing.EncodedObject) error) error {
- return ForEachIterator(iter, cb)
- }
-
- // Close releases any resources used by the iterator.
- func (iter *EncodedObjectSliceIter) Close() {
- iter.series = []plumbing.EncodedObject{}
- }
-
- // MultiEncodedObjectIter implements EncodedObjectIter. It iterates over several
- // EncodedObjectIter,
- //
- // The MultiObjectIter must be closed with a call to Close() when it is no
- // longer needed.
- type MultiEncodedObjectIter struct {
- iters []EncodedObjectIter
- }
-
- // NewMultiEncodedObjectIter returns an object iterator for the given slice of
- // EncodedObjectIters.
- func NewMultiEncodedObjectIter(iters []EncodedObjectIter) EncodedObjectIter {
- return &MultiEncodedObjectIter{iters: iters}
- }
-
- // Next returns the next object from the iterator, if one iterator reach io.EOF
- // is removed and the next one is used.
- func (iter *MultiEncodedObjectIter) Next() (plumbing.EncodedObject, error) {
- if len(iter.iters) == 0 {
- return nil, io.EOF
- }
-
- obj, err := iter.iters[0].Next()
- if err == io.EOF {
- iter.iters[0].Close()
- iter.iters = iter.iters[1:]
- return iter.Next()
- }
-
- return obj, err
- }
-
- // ForEach call the cb function for each object 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 *MultiEncodedObjectIter) ForEach(cb func(plumbing.EncodedObject) error) error {
- return ForEachIterator(iter, cb)
- }
-
- // Close releases any resources used by the iterator.
- func (iter *MultiEncodedObjectIter) Close() {
- for _, i := range iter.iters {
- i.Close()
- }
- }
-
- type bareIterator interface {
- Next() (plumbing.EncodedObject, error)
- Close()
- }
-
- // ForEachIterator is a helper function to build iterators without need to
- // rewrite the same ForEach function each time.
- func ForEachIterator(iter bareIterator, cb func(plumbing.EncodedObject) error) error {
- defer iter.Close()
- for {
- obj, err := iter.Next()
- if err != nil {
- if err == io.EOF {
- return nil
- }
-
- return err
- }
-
- if err := cb(obj); err != nil {
- if err == ErrStop {
- return nil
- }
-
- return err
- }
- }
- }
|