diff options
author | Jeremy Stribling <strib@alum.mit.edu> | 2017-11-29 14:15:32 -0800 |
---|---|---|
committer | Jeremy Stribling <strib@alum.mit.edu> | 2017-11-29 14:29:19 -0800 |
commit | 4c1569511db5e1d26e42e9cd8dadb9e65ccafb20 (patch) | |
tree | 38e12de7c82d8c36d215775c13d17d3e566b2069 | |
parent | b18457df6a1f75283d95999fde5c162ba1a19651 (diff) | |
download | go-git-4c1569511db5e1d26e42e9cd8dadb9e65ccafb20.tar.gz |
storer: separate loose and packed object mgmt into optional ifaces
Suggested by mcuadros.
-rw-r--r-- | plumbing/storer/object.go | 40 | ||||
-rw-r--r-- | plumbing/storer/object_test.go | 21 | ||||
-rw-r--r-- | prune.go | 20 | ||||
-rw-r--r-- | repository.go | 26 |
4 files changed, 58 insertions, 49 deletions
diff --git a/plumbing/storer/object.go b/plumbing/storer/object.go index e5f98d7..f1d19ef 100644 --- a/plumbing/storer/object.go +++ b/plumbing/storer/object.go @@ -40,6 +40,26 @@ type EncodedObjectStorer interface { // HasEncodedObject returns ErrObjNotFound if the object doesn't // exist. If the object does exist, it returns nil. HasEncodedObject(plumbing.Hash) 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. @@ -52,6 +72,11 @@ type EncodedObjectStorer interface { 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) @@ -60,21 +85,6 @@ type EncodedObjectStorer interface { DeleteOldObjectPackAndIndex(plumbing.Hash, time.Time) 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 -} - // PackfileWriter is a optional method for ObjectStorer, it enable direct write // of packfile to the storage type PackfileWriter interface { diff --git a/plumbing/storer/object_test.go b/plumbing/storer/object_test.go index 9a6959d..6b4fe0f 100644 --- a/plumbing/storer/object_test.go +++ b/plumbing/storer/object_test.go @@ -3,7 +3,6 @@ package storer import ( "fmt" "testing" - "time" . "gopkg.in/check.v1" "gopkg.in/src-d/go-git.v4/plumbing" @@ -158,23 +157,3 @@ func (o *MockObjectStorage) IterEncodedObjects(t plumbing.ObjectType) (EncodedOb func (o *MockObjectStorage) Begin() Transaction { return nil } - -func (o *MockObjectStorage) ForEachObjectHash(fun func(plumbing.Hash) error) error { - return nil -} - -func (o *MockObjectStorage) LooseObjectTime(plumbing.Hash) (time.Time, error) { - return time.Time{}, plumbing.ErrObjectNotFound -} - -func (o *MockObjectStorage) DeleteLooseObject(plumbing.Hash) error { - return plumbing.ErrObjectNotFound -} - -func (o *MockObjectStorage) ObjectPacks() ([]plumbing.Hash, error) { - return nil, nil -} - -func (o *MockObjectStorage) DeleteOldObjectPackAndIndex(plumbing.Hash, time.Time) error { - return plumbing.ErrObjectNotFound -} @@ -1,9 +1,11 @@ package git import ( + "errors" "time" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/storer" ) type PruneHandler func(unreferencedObjectHash plumbing.Hash) error @@ -15,20 +17,32 @@ type PruneOptions struct { Handler PruneHandler } +var ErrLooseObjectsNotSupported = errors.New("Loose objects not supported") + // DeleteObject deletes an object from a repository. // The type conveniently matches PruneHandler. func (r *Repository) DeleteObject(hash plumbing.Hash) error { - return r.Storer.DeleteLooseObject(hash) + los, ok := r.Storer.(storer.LooseObjectStorer) + if !ok { + return ErrLooseObjectsNotSupported + } + + return los.DeleteLooseObject(hash) } func (r *Repository) Prune(opt PruneOptions) error { + los, ok := r.Storer.(storer.LooseObjectStorer) + if !ok { + return ErrLooseObjectsNotSupported + } + pw := newObjectWalker(r.Storer) err := pw.walkAllRefs() if err != nil { return err } // Now walk all (loose) objects in storage. - return r.Storer.ForEachObjectHash(func(hash plumbing.Hash) error { + return los.ForEachObjectHash(func(hash plumbing.Hash) error { // Get out if we have seen this object. if pw.isSeen(hash) { return nil @@ -38,7 +52,7 @@ func (r *Repository) Prune(opt PruneOptions) error { if opt.OnlyObjectsOlderThan != (time.Time{}) { // Errors here are non-fatal. The object may be e.g. packed. // Or concurrently deleted. Skip such objects. - t, err := r.Storer.LooseObjectTime(hash) + t, err := los.LooseObjectTime(hash) if err != nil { return nil } diff --git a/repository.go b/repository.go index d96399b..d7cca89 100644 --- a/repository.go +++ b/repository.go @@ -25,14 +25,15 @@ import ( ) var ( - ErrInvalidReference = errors.New("invalid reference, should be a tag or a branch") - ErrRepositoryNotExists = errors.New("repository does not exist") - ErrRepositoryAlreadyExists = errors.New("repository already exists") - ErrRemoteNotFound = errors.New("remote not found") - ErrRemoteExists = errors.New("remote already exists ") - ErrWorktreeNotProvided = errors.New("worktree should be provided") - ErrIsBareRepository = errors.New("worktree not available in a bare repository") - ErrUnableToResolveCommit = errors.New("unable to resolve commit") + ErrInvalidReference = errors.New("invalid reference, should be a tag or a branch") + ErrRepositoryNotExists = errors.New("repository does not exist") + ErrRepositoryAlreadyExists = errors.New("repository already exists") + ErrRemoteNotFound = errors.New("remote not found") + ErrRemoteExists = errors.New("remote already exists ") + ErrWorktreeNotProvided = errors.New("worktree should be provided") + ErrIsBareRepository = errors.New("worktree not available in a bare repository") + ErrUnableToResolveCommit = errors.New("unable to resolve commit") + ErrPackedObjectsNotSupported = errors.New("Packed objects not supported") ) // Repository represents a git repository @@ -1024,8 +1025,13 @@ type RepackConfig struct { } func (r *Repository) RepackObjects(cfg *RepackConfig) (err error) { + pos, ok := r.Storer.(storer.PackedObjectStorer) + if !ok { + return ErrPackedObjectsNotSupported + } + // Get the existing object packs. - hs, err := r.Storer.ObjectPacks() + hs, err := pos.ObjectPacks() if err != nil { return err } @@ -1042,7 +1048,7 @@ func (r *Repository) RepackObjects(cfg *RepackConfig) (err error) { if h == nh { continue } - err = r.Storer.DeleteOldObjectPackAndIndex(h, cfg.OnlyDeletePacksOlderThan) + err = pos.DeleteOldObjectPackAndIndex(h, cfg.OnlyDeletePacksOlderThan) if err != nil { return err } |