aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMáximo Cuadros <mcuadros@gmail.com>2016-11-07 20:29:58 +0100
committerGitHub <noreply@github.com>2016-11-07 20:29:58 +0100
commit0ff9ef2b44c53e557c78bde0fd9c29847e5f0e23 (patch)
treeb9c7485fe99e6e89fa736ceb0223aeb2ecddb77c
parentf6ed7424cbf33c7013332d7e95b4262a4bc4a523 (diff)
downloadgo-git-0ff9ef2b44c53e557c78bde0fd9c29847e5f0e23.tar.gz
global storage interface refactor (#112)
* core: ObjectStorage, ReferenceStorage renamed to ObjectStorer and ReferenceStorer * rebase * general, changes request by @alcortes * general, changes request by @alcortes
-rw-r--r--blobs.go2
-rw-r--r--clients/common/common.go5
-rw-r--r--commit.go8
-rw-r--r--commit_test.go2
-rw-r--r--common.go14
-rw-r--r--common_test.go4
-rw-r--r--config/config.go39
-rw-r--r--config/config_test.go20
-rw-r--r--core/memory.go7
-rw-r--r--core/object.go25
-rw-r--r--core/object_test.go8
-rw-r--r--core/reference.go8
-rw-r--r--core/storage.go72
-rw-r--r--examples/storage/aerospike/storage.go163
-rw-r--r--formats/config/common.go1
-rw-r--r--formats/config/doc.go3
-rw-r--r--formats/config/section.go47
-rw-r--r--formats/idxfile/decoder_test.go2
-rw-r--r--formats/packfile/decoder.go75
-rw-r--r--formats/packfile/decoder_test.go10
-rw-r--r--remote.go30
-rw-r--r--remote_test.go28
-rw-r--r--repository.go98
-rw-r--r--repository_test.go4
-rw-r--r--storage/filesystem/config.go124
-rw-r--r--storage/filesystem/config_test.go26
-rw-r--r--storage/filesystem/object.go41
-rw-r--r--storage/filesystem/object_test.go8
-rw-r--r--storage/filesystem/reference.go6
-rw-r--r--storage/filesystem/storage.go43
-rw-r--r--storage/filesystem/storage_test.go16
-rw-r--r--storage/memory/storage.go127
-rw-r--r--storage/memory/storage_test.go31
-rw-r--r--storage/test/storage_suite.go163
-rw-r--r--tag_test.go4
-rw-r--r--tree.go4
-rw-r--r--tree_test.go10
37 files changed, 548 insertions, 730 deletions
diff --git a/blobs.go b/blobs.go
index f720c86..4ecd989 100644
--- a/blobs.go
+++ b/blobs.go
@@ -60,7 +60,7 @@ func (b *Blob) Encode(o core.Object) error {
}
// Reader returns a reader allow the access to the content of the blob
-func (b *Blob) Reader() (core.ObjectReader, error) {
+func (b *Blob) Reader() (io.ReadCloser, error) {
return b.obj.Reader()
}
diff --git a/clients/common/common.go b/clients/common/common.go
index 8e8b2e2..c7cac00 100644
--- a/clients/common/common.go
+++ b/clients/common/common.go
@@ -110,10 +110,9 @@ func (i *GitUploadPackInfo) Decode(r io.Reader) error {
}
func (i *GitUploadPackInfo) addRefs(ar *advrefs.AdvRefs) error {
- i.Refs = make(memory.ReferenceStorage, 0)
for name, hash := range ar.References {
ref := core.NewReferenceFromStrings(name, hash.String())
- i.Refs.Set(ref)
+ i.Refs.SetReference(ref)
}
return i.addSymbolicRefs(ar)
@@ -133,7 +132,7 @@ func (i *GitUploadPackInfo) addSymbolicRefs(ar *advrefs.AdvRefs) error {
name := core.ReferenceName(chunks[0])
target := core.ReferenceName(chunks[1])
ref := core.NewSymbolicReference(name, target)
- i.Refs.Set(ref)
+ i.Refs.SetReference(ref)
}
return nil
diff --git a/commit.go b/commit.go
index a66cef8..c42236e 100644
--- a/commit.go
+++ b/commit.go
@@ -37,11 +37,9 @@ func (c *Commit) Tree() (*Tree, error) {
// Parents return a CommitIter to the parent Commits
func (c *Commit) Parents() *CommitIter {
- return NewCommitIter(c.r, core.NewObjectLookupIter(
- c.r.s.ObjectStorage(),
- core.CommitObject,
- c.parents,
- ))
+ return NewCommitIter(c.r,
+ core.NewObjectLookupIter(c.r.s, core.CommitObject, c.parents),
+ )
}
// NumParents returns the number of parents in a commit.
diff --git a/commit_test.go b/commit_test.go
index f55d01a..6d83aec 100644
--- a/commit_test.go
+++ b/commit_test.go
@@ -29,7 +29,7 @@ func (s *SuiteCommit) SetUpSuite(c *C) {
func (s *SuiteCommit) TestDecodeNonCommit(c *C) {
hash := core.NewHash("9a48f23120e880dfbe41f7c9b7b708e9ee62a492")
- blob, err := s.Repository.s.ObjectStorage().Get(core.AnyObject, hash)
+ blob, err := s.Repository.s.Object(core.AnyObject, hash)
c.Assert(err, IsNil)
commit := &Commit{}
diff --git a/common.go b/common.go
index 560c2c0..2a55a37 100644
--- a/common.go
+++ b/common.go
@@ -8,11 +8,14 @@ import (
"gopkg.in/src-d/go-git.v4/core"
)
-// Storage storage of objects and references
-type Storage interface {
- ConfigStorage() config.ConfigStorage
- ObjectStorage() core.ObjectStorage
- ReferenceStorage() core.ReferenceStorage
+// Storer is a generic storage of objects, references and any information
+// related to a particular repository. Some Storer implementations persist the
+// information in an system directory (such as `.git`) and others
+// implementations are in memmory being ephemeral
+type Storer interface {
+ core.ObjectStorer
+ core.ReferenceStorer
+ config.ConfigStorer
}
// countLines returns the number of lines in a string à la git, this is
@@ -52,4 +55,5 @@ func checkClose(c io.Closer, err *error) {
}
}
+// DateFormat is the format being use in the orignal git implementation
const DateFormat = "Mon Jan 02 15:04:05 2006 -0700"
diff --git a/common_test.go b/common_test.go
index 854db3a..672a157 100644
--- a/common_test.go
+++ b/common_test.go
@@ -57,7 +57,7 @@ func (s *BaseSuite) buildRepositories(c *C, f fixtures.Fixtures) {
defer f.Close()
n := packfile.NewScanner(f)
- d, err := packfile.NewDecoder(n, r.s.ObjectStorage())
+ d, err := packfile.NewDecoder(n, r.s)
c.Assert(err, IsNil)
_, err = d.Decode()
c.Assert(err, IsNil)
@@ -155,7 +155,7 @@ func unpackFixtures(c *C, fixtures ...[]packedFixture) map[string]*Repository {
c.Assert(err, IsNil, comment)
r := packfile.NewScanner(f)
- d, err := packfile.NewDecoder(r, repos[fixture.url].s.ObjectStorage())
+ d, err := packfile.NewDecoder(r, repos[fixture.url].s)
c.Assert(err, IsNil, comment)
_, err = d.Decode()
c.Assert(err, IsNil, comment)
diff --git a/config/config.go b/config/config.go
index f94d4c9..b7482ea 100644
--- a/config/config.go
+++ b/config/config.go
@@ -7,22 +7,51 @@ import (
)
const (
+ // DefaultRefSpec is the default refspec used, when none is given
DefaultRefSpec = "+refs/heads/*:refs/remotes/%s/*"
)
+// ConfigStorer interface to persist Config objects
+type ConfigStorer interface {
+ Config() (*Config, error)
+ SetConfig(*Config) error
+}
+
var (
+ ErrInvalid = errors.New("config invalid remote")
ErrRemoteConfigNotFound = errors.New("remote config not found")
ErrRemoteConfigEmptyURL = errors.New("remote config: empty URL")
ErrRemoteConfigEmptyName = errors.New("remote config: empty name")
)
-type ConfigStorage interface {
- Remote(name string) (*RemoteConfig, error)
- Remotes() ([]*RemoteConfig, error)
- SetRemote(*RemoteConfig) error
- DeleteRemote(name string) error
+// Config contains the repository configuration
+type Config struct {
+ Remotes map[string]*RemoteConfig
+}
+
+// NewConfig returns a new empty Config
+func NewConfig() *Config {
+ return &Config{
+ Remotes: make(map[string]*RemoteConfig, 0),
+ }
+}
+
+// Validate validate the fields and set the default values
+func (c *Config) Validate() error {
+ for name, r := range c.Remotes {
+ if r.Name != name {
+ return ErrInvalid
+ }
+
+ if err := r.Validate(); err != nil {
+ return err
+ }
+ }
+
+ return nil
}
+// RemoteConfig contains the configuration for a given repository
type RemoteConfig struct {
Name string
URL string
diff --git a/config/config_test.go b/config/config_test.go
index d97053b..f2539d0 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -6,6 +6,26 @@ type ConfigSuite struct{}
var _ = Suite(&ConfigSuite{})
+func (s *ConfigSuite) TestConfigValidateInvalidRemote(c *C) {
+ config := &Config{
+ Remotes: map[string]*RemoteConfig{
+ "foo": {Name: "foo"},
+ },
+ }
+
+ c.Assert(config.Validate(), Equals, ErrRemoteConfigEmptyURL)
+}
+
+func (s *ConfigSuite) TestConfigValidateInvalidKey(c *C) {
+ config := &Config{
+ Remotes: map[string]*RemoteConfig{
+ "bar": {Name: "foo"},
+ },
+ }
+
+ c.Assert(config.Validate(), Equals, ErrInvalid)
+}
+
func (s *ConfigSuite) TestRemoteConfigValidateMissingURL(c *C) {
config := &RemoteConfig{Name: "foo"}
c.Assert(config.Validate(), Equals, ErrRemoteConfigEmptyURL)
diff --git a/core/memory.go b/core/memory.go
index 97b1b9b..dabee3a 100644
--- a/core/memory.go
+++ b/core/memory.go
@@ -1,7 +1,8 @@
-package core
+package core
import (
"bytes"
+ "io"
"io/ioutil"
)
@@ -39,12 +40,12 @@ func (o *MemoryObject) Size() int64 { return o.sz }
func (o *MemoryObject) SetSize(s int64) { o.sz = s }
// Reader returns a ObjectReader used to read the object's content.
-func (o *MemoryObject) Reader() (ObjectReader, error) {
+func (o *MemoryObject) Reader() (io.ReadCloser, error) {
return ioutil.NopCloser(bytes.NewBuffer(o.cont)), nil
}
// Writer returns a ObjectWriter used to write the object's content.
-func (o *MemoryObject) Writer() (ObjectWriter, error) {
+func (o *MemoryObject) Writer() (io.WriteCloser, error) {
return o, nil
}
diff --git a/core/object.go b/core/object.go
index 30beff8..8125465 100644
--- a/core/object.go
+++ b/core/object.go
@@ -12,21 +12,6 @@ var (
ErrInvalidType = errors.New("invalid object type")
)
-// TODO: Consider adding a Hash function to the ObjectReader and ObjectWriter
-// interfaces that returns the hash calculated for the reader or writer.
-
-// ObjectReader is a generic representation of an object reader.
-//
-// ObjectReader implements io.ReadCloser. Close should be called when finished
-// with it.
-type ObjectReader io.ReadCloser
-
-// ObjectWriter is a generic representation of an object writer.
-//
-// ObjectWriter implements io.WriterCloser. Close should be called when finished
-// with it.
-type ObjectWriter io.WriteCloser
-
// Object is a generic representation of any git object
type Object interface {
Hash() Hash
@@ -34,8 +19,8 @@ type Object interface {
SetType(ObjectType)
Size() int64
SetSize(int64)
- Reader() (ObjectReader, error)
- Writer() (ObjectWriter, error)
+ Reader() (io.ReadCloser, error)
+ Writer() (io.WriteCloser, error)
}
// ObjectType internal object type
@@ -116,7 +101,7 @@ func ParseObjectType(value string) (typ ObjectType, err error) {
// The ObjectLookupIter must be closed with a call to Close() when it is no
// longer needed.
type ObjectLookupIter struct {
- storage ObjectStorage
+ storage ObjectStorer
series []Hash
t ObjectType
pos int
@@ -124,7 +109,7 @@ type ObjectLookupIter struct {
// NewObjectLookupIter returns an object iterator given an object storage and
// a slice of object hashes.
-func NewObjectLookupIter(storage ObjectStorage, t ObjectType, series []Hash) *ObjectLookupIter {
+func NewObjectLookupIter(storage ObjectStorer, t ObjectType, series []Hash) *ObjectLookupIter {
return &ObjectLookupIter{
storage: storage,
series: series,
@@ -142,7 +127,7 @@ func (iter *ObjectLookupIter) Next() (Object, error) {
}
hash := iter.series[iter.pos]
- obj, err := iter.storage.Get(iter.t, hash)
+ obj, err := iter.storage.Object(iter.t, hash)
if err == nil {
iter.pos++
}
diff --git a/core/object_test.go b/core/object_test.go
index d087aae..5ebf26a 100644
--- a/core/object_test.go
+++ b/core/object_test.go
@@ -159,18 +159,18 @@ func (o *MockObjectStorage) NewObject() Object {
return nil
}
-func (o *MockObjectStorage) Set(obj Object) (Hash, error) {
+func (o *MockObjectStorage) SetObject(obj Object) (Hash, error) {
return ZeroHash, nil
}
-func (o *MockObjectStorage) Get(t ObjectType, h Hash) (Object, error) {
+func (o *MockObjectStorage) Object(t ObjectType, h Hash) (Object, error) {
return &MemoryObject{h: h}, nil
}
-func (o *MockObjectStorage) Iter(t ObjectType) (ObjectIter, error) {
+func (o *MockObjectStorage) IterObjects(t ObjectType) (ObjectIter, error) {
return nil, nil
}
-func (o *MockObjectStorage) Begin() TxObjectStorage {
+func (o *MockObjectStorage) Begin() Transaction {
return nil
}
diff --git a/core/reference.go b/core/reference.go
index 16b60ac..ee55a6a 100644
--- a/core/reference.go
+++ b/core/reference.go
@@ -203,15 +203,15 @@ func (iter *ReferenceSliceIter) Close() {
iter.pos = len(iter.series)
}
-func ResolveReference(s ReferenceStorage, n ReferenceName) (*Reference, error) {
- r, err := s.Get(n)
+func ResolveReference(s ReferenceStorer, n ReferenceName) (*Reference, error) {
+ r, err := s.Reference(n)
if err != nil || r == nil {
return r, err
}
return resolveReference(s, r, 0)
}
-func resolveReference(s ReferenceStorage, r *Reference, recursion int) (*Reference, error) {
+func resolveReference(s ReferenceStorer, r *Reference, recursion int) (*Reference, error) {
if r.Type() != SymbolicReference {
return r, nil
}
@@ -220,7 +220,7 @@ func resolveReference(s ReferenceStorage, r *Reference, recursion int) (*Referen
return nil, ErrMaxResolveRecursion
}
- t, err := s.Get(r.Target())
+ t, err := s.Reference(r.Target())
if err != nil {
return nil, err
}
diff --git a/core/storage.go b/core/storage.go
index 739dfb6..101115b 100644
--- a/core/storage.go
+++ b/core/storage.go
@@ -7,45 +7,49 @@ import (
var (
//ErrStop is used to stop a ForEach function in an Iter
- ErrStop = errors.New("stop iter")
- ErrNotImplemented = errors.New("method not-implemented")
+ ErrStop = errors.New("stop iter")
)
-// ObjectStorage generic storage of objects
-type ObjectStorage interface {
+// ObjectStorer generic storage of objects
+type ObjectStorer interface {
// NewObject returns a new Object, the real type of the object can be a
// custom implementation or the defaul one, MemoryObject
NewObject() Object
- // Set save an object into the storage, the object shuld be create with
- // the NewObject, method, and file if the type is not supported.
- Set(Object) (Hash, error)
- // Get an object by hash with the given ObjectType. Implementors should
- // return (nil, ErrObjectNotFound) if an object doesn't exist with both the
- // given hash and object type.
+ // SetObject save an object into the storage, the object shuld be create
+ // with the NewObject, method, and file if the type is not supported.
+ SetObject(Object) (Hash, error)
+ // Object an object by hash with the given ObjectType. Implementors
+ // should return (nil, ErrObjectNotFound) if an object doesn't exist with
+ // both the given hash and object type.
//
// Valid ObjectType values are CommitObject, BlobObject, TagObject,
- // TreeObject and AnyObject.
- //
- // If AnyObject is given, the object must be looked up regardless of its type.
- Get(ObjectType, Hash) (Object, error)
- // Iter returns a custom ObjectIter over all the object on the storage.
+ // TreeObject and AnyObject. If AnyObject is given, the object must be
+ // looked up regardless of its type.
+ Object(ObjectType, Hash) (Object, error)
+ // IterObjects returns a custom ObjectIter over all the object on the
+ // storage.
//
// Valid ObjectType values are CommitObject, BlobObject, TagObject,
- Iter(ObjectType) (ObjectIter, error)
+ IterObjects(ObjectType) (ObjectIter, 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() TxObjectStorage
+ Begin() Transaction
}
-// ObjectStorageWrite is a optional method for ObjectStorage, it enable direct
-// write of packfile to the storage
-type ObjectStorageWrite interface {
- // Writer retuns a writer for writing a packfile to the Storage, this method
- // is optional, if not implemented the ObjectStorage should return a
- // ErrNotImplemented error.
+// PackfileWriter is a optional method for ObjectStorer, it enable direct write
+// of packfile to the storage
+type PackfileWriter interface {
+ // PackfileWriter retuns a writer for writing a packfile to the Storage,
+ // this method is optional, if not implemented the ObjectStorer should
+ // return a ErrNotImplemented error.
//
// If the implementation not implements Writer the objects should be written
// using the Set method.
- Writer() (io.WriteCloser, error)
+ PackfileWriter() (io.WriteCloser, error)
}
// ObjectIter is a generic closable interface for iterating over objects.
@@ -55,20 +59,20 @@ type ObjectIter interface {
Close()
}
-// TxObjectStorage is an in-progress storage transaction.
-// A transaction must end with a call to Commit or Rollback.
-type TxObjectStorage interface {
- Set(Object) (Hash, error)
- Get(ObjectType, Hash) (Object, error)
+// Transaction is an in-progress storage transaction. A transaction must end
+// with a call to Commit or Rollback.
+type Transaction interface {
+ SetObject(Object) (Hash, error)
+ Object(ObjectType, Hash) (Object, error)
Commit() error
Rollback() error
}
-// ReferenceStorage generic storage of references
-type ReferenceStorage interface {
- Set(*Reference) error
- Get(ReferenceName) (*Reference, error)
- Iter() (ReferenceIter, error)
+// ReferenceStorer generic storage of references
+type ReferenceStorer interface {
+ SetReference(*Reference) error
+ Reference(ReferenceName) (*Reference, error)
+ IterReferences() (ReferenceIter, error)
}
// ReferenceIter is a generic closable interface for iterating over references
diff --git a/examples/storage/aerospike/storage.go b/examples/storage/aerospike/storage.go
index a9312ce..776fc33 100644
--- a/examples/storage/aerospike/storage.go
+++ b/examples/storage/aerospike/storage.go
@@ -15,17 +15,13 @@ import (
const (
urlField = "url"
referencesSet = "reference"
- remotesSet = "remote"
+ configSet = "config"
)
type Storage struct {
client *driver.Client
ns string
url string
-
- os *ObjectStorage
- rs *ReferenceStorage
- cs *ConfigStorage
}
func NewStorage(client *driver.Client, ns, url string) (*Storage, error) {
@@ -36,46 +32,11 @@ func NewStorage(client *driver.Client, ns, url string) (*Storage, error) {
return &Storage{client: client, ns: ns, url: url}, nil
}
-func (s *Storage) ObjectStorage() core.ObjectStorage {
- if s.os == nil {
- s.os = &ObjectStorage{s.client, s.ns, s.url}
- }
-
- return s.os
-}
-
-func (s *Storage) ReferenceStorage() core.ReferenceStorage {
- if s.rs == nil {
- s.rs = &ReferenceStorage{s.client, s.ns, s.url}
- }
-
- return s.rs
-}
-
-func (s *Storage) ConfigStorage() config.ConfigStorage {
- if s.cs == nil {
- s.cs = &ConfigStorage{s.client, s.ns, s.url}
- }
-
- return s.cs
-}
-
-type ObjectStorage struct {
- client *driver.Client
- ns string
- url string
-}
-
-func (s *ObjectStorage) NewObject() core.Object {
+func (s *Storage) NewObject() core.Object {
return &core.MemoryObject{}
}
-// Writer method not supported, this method is optional to implemented.
-func (s *ObjectStorage) Writer() (io.WriteCloser, error) {
- return nil, core.ErrNotImplemented
-}
-
-func (s *ObjectStorage) Set(obj core.Object) (core.Hash, error) {
+func (s *Storage) SetObject(obj core.Object) (core.Hash, error) {
key, err := s.buildKey(obj.Hash(), obj.Type())
if err != nil {
return obj.Hash(), err
@@ -102,7 +63,7 @@ func (s *ObjectStorage) Set(obj core.Object) (core.Hash, error) {
return obj.Hash(), err
}
-func (s *ObjectStorage) Get(t core.ObjectType, h core.Hash) (core.Object, error) {
+func (s *Storage) Object(t core.ObjectType, h core.Hash) (core.Object, error) {
key, err := s.buildKey(h, t)
if err != nil {
return nil, err
@@ -120,7 +81,7 @@ func (s *ObjectStorage) Get(t core.ObjectType, h core.Hash) (core.Object, error)
return objectFromRecord(rec, t)
}
-func (s *ObjectStorage) Iter(t core.ObjectType) (core.ObjectIter, error) {
+func (s *Storage) IterObjects(t core.ObjectType) (core.ObjectIter, error) {
stmnt := driver.NewStatement(s.ns, t.String())
err := stmnt.Addfilter(driver.NewEqualFilter(urlField, s.url))
@@ -132,34 +93,10 @@ func (s *ObjectStorage) Iter(t core.ObjectType) (core.ObjectIter, error) {
return &ObjectIter{t, rs.Records}, nil
}
-func (s *ObjectStorage) buildKey(h core.Hash, t core.ObjectType) (*driver.Key, error) {
+func (s *Storage) buildKey(h core.Hash, t core.ObjectType) (*driver.Key, error) {
return driver.NewKey(s.ns, t.String(), fmt.Sprintf("%s|%s", s.url, h.String()))
}
-func (s *ObjectStorage) Begin() core.TxObjectStorage {
- return &TxObjectStorage{Storage: s}
-}
-
-type TxObjectStorage struct {
- Storage *ObjectStorage
-}
-
-func (tx *TxObjectStorage) Get(t core.ObjectType, h core.Hash) (core.Object, error) {
- return tx.Storage.Get(t, h)
-}
-
-func (tx *TxObjectStorage) Set(obj core.Object) (core.Hash, error) {
- return tx.Storage.Set(obj)
-}
-
-func (tx *TxObjectStorage) Commit() error {
- return nil
-}
-
-func (tx *TxObjectStorage) Rollback() error {
- return nil
-}
-
type ObjectIter struct {
t core.ObjectType
ch chan *driver.Record
@@ -212,15 +149,8 @@ func objectFromRecord(r *driver.Record, t core.ObjectType) (core.Object, error)
return o, nil
}
-type ReferenceStorage struct {
- client *driver.Client
- ns string
- url string
-}
-
-// Set stores a reference.
-func (s *ReferenceStorage) Set(ref *core.Reference) error {
- key, err := s.buildKey(ref.Name())
+func (s *Storage) SetReference(ref *core.Reference) error {
+ key, err := s.buildReferenceKey(ref.Name())
if err != nil {
return err
}
@@ -235,9 +165,8 @@ func (s *ReferenceStorage) Set(ref *core.Reference) error {
return s.client.Put(nil, key, bins)
}
-// Get returns a stored reference with the given name
-func (s *ReferenceStorage) Get(n core.ReferenceName) (*core.Reference, error) {
- key, err := s.buildKey(n)
+func (s *Storage) Reference(n core.ReferenceName) (*core.Reference, error) {
+ key, err := s.buildReferenceKey(n)
if err != nil {
return nil, err
}
@@ -253,12 +182,11 @@ func (s *ReferenceStorage) Get(n core.ReferenceName) (*core.Reference, error) {
), nil
}
-func (s *ReferenceStorage) buildKey(n core.ReferenceName) (*driver.Key, error) {
+func (s *Storage) buildReferenceKey(n core.ReferenceName) (*driver.Key, error) {
return driver.NewKey(s.ns, referencesSet, fmt.Sprintf("%s|%s", s.url, n))
}
-// Iter returns a core.ReferenceIter
-func (s *ReferenceStorage) Iter() (core.ReferenceIter, error) {
+func (s *Storage) IterReferences() (core.ReferenceIter, error) {
stmnt := driver.NewStatement(s.ns, referencesSet)
err := stmnt.Addfilter(driver.NewEqualFilter(urlField, s.url))
if err != nil {
@@ -281,14 +209,8 @@ func (s *ReferenceStorage) Iter() (core.ReferenceIter, error) {
return core.NewReferenceSliceIter(refs), nil
}
-type ConfigStorage struct {
- client *driver.Client
- ns string
- url string
-}
-
-func (s *ConfigStorage) Remote(name string) (*config.RemoteConfig, error) {
- key, err := s.buildRemoteKey(name)
+func (s *Storage) Config() (*config.Config, error) {
+ key, err := s.buildConfigKey()
if err != nil {
return nil, err
}
@@ -298,44 +220,12 @@ func (s *ConfigStorage) Remote(name string) (*config.RemoteConfig, error) {
return nil, err
}
- return remoteFromRecord(rec)
-}
-
-func remoteFromRecord(r *driver.Record) (*config.RemoteConfig, error) {
- content := r.Bins["blob"].([]byte)
-
- c := &config.RemoteConfig{}
- return c, json.Unmarshal(content, c)
-}
-
-func (s *ConfigStorage) Remotes() ([]*config.RemoteConfig, error) {
- stmnt := driver.NewStatement(s.ns, remotesSet)
- err := stmnt.Addfilter(driver.NewEqualFilter(urlField, s.url))
- if err != nil {
- return nil, err
- }
-
- rs, err := s.client.Query(nil, stmnt)
- if err != nil {
- return nil, err
- return nil, err
- }
-
- var remotes []*config.RemoteConfig
- for r := range rs.Records {
- remote, err := remoteFromRecord(r)
- if err != nil {
- return nil, err
- }
-
- remotes = append(remotes, remote)
- }
-
- return remotes, nil
+ c := &config.Config{}
+ return c, json.Unmarshal(rec.Bins["blob"].([]byte), c)
}
-func (s *ConfigStorage) SetRemote(r *config.RemoteConfig) error {
- key, err := s.buildRemoteKey(r.Name)
+func (s *Storage) SetConfig(r *config.Config) error {
+ key, err := s.buildConfigKey()
if err != nil {
return err
}
@@ -347,31 +237,20 @@ func (s *ConfigStorage) SetRemote(r *config.RemoteConfig) error {
bins := driver.BinMap{
urlField: s.url,
- "name": r.Name,
"blob": json,
}
return s.client.Put(nil, key, bins)
}
-func (s *ConfigStorage) DeleteRemote(name string) error {
- key, err := s.buildRemoteKey(name)
- if err != nil {
- return err
- }
-
- _, err = s.client.Delete(nil, key)
- return err
-}
-
-func (s *ConfigStorage) buildRemoteKey(name string) (*driver.Key, error) {
- return driver.NewKey(s.ns, remotesSet, fmt.Sprintf("%s|%s", s.url, name))
+func (s *Storage) buildConfigKey() (*driver.Key, error) {
+ return driver.NewKey(s.ns, configSet, fmt.Sprintf("%s|config", s.url))
}
func createIndexes(c *driver.Client, ns string) error {
for _, set := range [...]string{
referencesSet,
- remotesSet,
+ configSet,
core.BlobObject.String(),
core.TagObject.String(),
core.TreeObject.String(),
diff --git a/formats/config/common.go b/formats/config/common.go
index e7292e9..d2f1e5c 100644
--- a/formats/config/common.go
+++ b/formats/config/common.go
@@ -32,6 +32,7 @@ func (c *Config) Section(name string) *Section {
return s
}
}
+
s := &Section{Name: name}
c.Sections = append(c.Sections, s)
return s
diff --git a/formats/config/doc.go b/formats/config/doc.go
index 1f7eb78..dd77fbc 100644
--- a/formats/config/doc.go
+++ b/formats/config/doc.go
@@ -1,5 +1,4 @@
-// Package config implements decoding, encoding and manipulation
-// of git config files.
+// Package config implements decoding/encoding of git config files.
package config
/*
diff --git a/formats/config/section.go b/formats/config/section.go
index 552ce74..1844913 100644
--- a/formats/config/section.go
+++ b/formats/config/section.go
@@ -21,28 +21,15 @@ func (s *Section) IsName(name string) bool {
return strings.ToLower(s.Name) == strings.ToLower(name)
}
-func (s *Subsection) IsName(name string) bool {
- return s.Name == name
-}
-
func (s *Section) Option(key string) string {
return s.Options.Get(key)
}
-func (s *Subsection) Option(key string) string {
- return s.Options.Get(key)
-}
-
func (s *Section) AddOption(key string, value string) *Section {
s.Options = s.Options.withAddedOption(key, value)
return s
}
-func (s *Subsection) AddOption(key string, value string) *Subsection {
- s.Options = s.Options.withAddedOption(key, value)
- return s
-}
-
func (s *Section) SetOption(key string, value string) *Section {
s.Options = s.Options.withSettedOption(key, value)
return s
@@ -53,16 +40,6 @@ func (s *Section) RemoveOption(key string) *Section {
return s
}
-func (s *Subsection) SetOption(key string, value string) *Subsection {
- s.Options = s.Options.withSettedOption(key, value)
- return s
-}
-
-func (s *Subsection) RemoveOption(key string) *Subsection {
- s.Options = s.Options.withoutOption(key)
- return s
-}
-
func (s *Section) Subsection(name string) *Subsection {
for i := len(s.Subsections) - 1; i >= 0; i-- {
ss := s.Subsections[i]
@@ -70,6 +47,7 @@ func (s *Section) Subsection(name string) *Subsection {
return ss
}
}
+
ss := &Subsection{Name: name}
s.Subsections = append(s.Subsections, ss)
return ss
@@ -84,3 +62,26 @@ func (s *Section) HasSubsection(name string) bool {
return false
}
+
+func (s *Subsection) IsName(name string) bool {
+ return s.Name == name
+}
+
+func (s *Subsection) Option(key string) string {
+ return s.Options.Get(key)
+}
+
+func (s *Subsection) AddOption(key string, value string) *Subsection {
+ s.Options = s.Options.withAddedOption(key, value)
+ return s
+}
+
+func (s *Subsection) SetOption(key string, value string) *Subsection {
+ s.Options = s.Options.withSettedOption(key, value)
+ return s
+}
+
+func (s *Subsection) RemoveOption(key string) *Subsection {
+ s.Options = s.Options.withoutOption(key)
+ return s
+}
diff --git a/formats/idxfile/decoder_test.go b/formats/idxfile/decoder_test.go
index 02167a7..18546d2 100644
--- a/formats/idxfile/decoder_test.go
+++ b/formats/idxfile/decoder_test.go
@@ -42,7 +42,7 @@ func (s *IdxfileSuite) TestDecodeCRCs(c *C) {
scanner := packfile.NewScanner(f.Packfile())
storage := memory.NewStorage()
- pd, err := packfile.NewDecoder(scanner, storage.ObjectStorage())
+ pd, err := packfile.NewDecoder(scanner, storage)
c.Assert(err, IsNil)
_, err = pd.Decode()
c.Assert(err, IsNil)
diff --git a/formats/packfile/decoder.go b/formats/packfile/decoder.go
index 4606a3f..e96980a 100644
--- a/formats/packfile/decoder.go
+++ b/formats/packfile/decoder.go
@@ -37,13 +37,15 @@ var (
// reader and without a core.ObjectStorage or ReadObjectAt method is called
// without a seekable scanner
ErrNonSeekable = NewError("non-seekable scanner")
+ // ErrRollback error making Rollback over a transaction after an error
+ ErrRollback = NewError("rollback error, during set error")
)
// Decoder reads and decodes packfiles from an input stream.
type Decoder struct {
s *Scanner
- o core.ObjectStorage
- tx core.TxObjectStorage
+ o core.ObjectStorer
+ tx core.Transaction
offsetToHash map[int64]core.Hash
hashToOffset map[core.Hash]int64
@@ -51,20 +53,14 @@ type Decoder struct {
}
// NewDecoder returns a new Decoder that reads from r.
-func NewDecoder(s *Scanner, o core.ObjectStorage) (*Decoder, error) {
+func NewDecoder(s *Scanner, o core.ObjectStorer) (*Decoder, error) {
if !s.IsSeekable && o == nil {
return nil, ErrNonSeekable
}
- var tx core.TxObjectStorage
- if o != nil {
- tx = o.Begin()
- }
-
return &Decoder{
- s: s,
- o: o,
- tx: tx,
+ s: s,
+ o: o,
offsetToHash: make(map[int64]core.Hash, 0),
hashToOffset: make(map[core.Hash]int64, 0),
@@ -87,39 +83,64 @@ func (d *Decoder) doDecode() error {
return err
}
- if d.o == nil {
- return d.readObjects(count)
+ _, isTxStorer := d.o.(core.Transactioner)
+ switch {
+ case d.o == nil:
+ return d.readObjects(int(count))
+ case isTxStorer:
+ return d.readObjectsWithObjectStorerTx(int(count))
+ default:
+ return d.readObjectsWithObjectStorer(int(count))
}
+}
- if err := d.readObjects(count); err != nil {
- if err := d.tx.Rollback(); err != nil {
- return nil
+func (d *Decoder) readObjects(count int) error {
+ for i := 0; i < count; i++ {
+ if _, err := d.ReadObject(); err != nil {
+ return err
}
-
- return err
}
- return d.tx.Commit()
+ return nil
}
-func (d *Decoder) readObjects(count uint32) error {
- for i := 0; i < int(count); i++ {
+func (d *Decoder) readObjectsWithObjectStorer(count int) error {
+ for i := 0; i < count; i++ {
obj, err := d.ReadObject()
if err != nil {
return err
}
- if d.o == nil {
- continue
+ if _, err := d.o.SetObject(obj); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (d *Decoder) readObjectsWithObjectStorerTx(count int) error {
+ tx := d.o.(core.Transactioner).Begin()
+
+ for i := 0; i < count; i++ {
+ obj, err := d.ReadObject()
+ if err != nil {
+ return err
}
- if _, err := d.tx.Set(obj); err != nil {
+ if _, err := tx.SetObject(obj); err != nil {
+ if rerr := d.tx.Rollback(); rerr != nil {
+ return ErrRollback.AddDetails(
+ "error: %s, during tx.Set error: %s", rerr, err,
+ )
+ }
+
return err
}
}
- return nil
+ return tx.Commit()
}
// ReadObject reads a object from the stream and return it
@@ -241,7 +262,7 @@ func (d *Decoder) recallByOffset(o int64) (core.Object, error) {
}
if h, ok := d.offsetToHash[o]; ok {
- return d.tx.Get(core.AnyObject, h)
+ return d.tx.Object(core.AnyObject, h)
}
return nil, core.ErrObjectNotFound
@@ -254,7 +275,7 @@ func (d *Decoder) recallByHash(h core.Hash) (core.Object, error) {
}
}
- obj, err := d.tx.Get(core.AnyObject, h)
+ obj, err := d.tx.Object(core.AnyObject, h)
if err != core.ErrObjectNotFound {
return obj, err
}
diff --git a/formats/packfile/decoder_test.go b/formats/packfile/decoder_test.go
index 48790b4..aa178d7 100644
--- a/formats/packfile/decoder_test.go
+++ b/formats/packfile/decoder_test.go
@@ -33,7 +33,7 @@ func (s *ReaderSuite) TestDecode(c *C) {
scanner := NewScanner(f.Packfile())
storage := memory.NewStorage()
- d, err := NewDecoder(scanner, storage.ObjectStorage())
+ d, err := NewDecoder(scanner, storage)
c.Assert(err, IsNil)
defer d.Close()
@@ -97,7 +97,7 @@ func (s *ReaderSuite) TestDecodeCRCs(c *C) {
scanner := NewScanner(f.Packfile())
storage := memory.NewStorage()
- d, err := NewDecoder(scanner, storage.ObjectStorage())
+ d, err := NewDecoder(scanner, storage)
c.Assert(err, IsNil)
_, err = d.Decode()
c.Assert(err, IsNil)
@@ -158,11 +158,9 @@ func (s *ReaderSuite) TestSetOffsets(c *C) {
}
func assertObjects(c *C, s *memory.Storage, expects []string) {
- o := s.ObjectStorage().(*memory.ObjectStorage)
-
- c.Assert(len(expects), Equals, len(o.Objects))
+ c.Assert(len(expects), Equals, len(s.Objects))
for _, exp := range expects {
- obt, err := o.Get(core.AnyObject, core.NewHash(exp))
+ obt, err := s.Object(core.AnyObject, core.NewHash(exp))
c.Assert(err, IsNil)
c.Assert(obt.Hash().String(), Equals, exp)
}
diff --git a/remote.go b/remote.go
index e7028e8..518a2b1 100644
--- a/remote.go
+++ b/remote.go
@@ -18,14 +18,14 @@ var NoErrAlreadyUpToDate = errors.New("already up-to-date")
// Remote represents a connection to a remote repository
type Remote struct {
c *config.RemoteConfig
- s Storage
+ s Storer
// cache fields, there during the connection is open
upSrv common.GitUploadPackService
upInfo *common.GitUploadPackInfo
}
-func newRemote(s Storage, c *config.RemoteConfig) *Remote {
+func newRemote(s Storer, c *config.RemoteConfig) *Remote {
return &Remote{s: s, c: c}
}
@@ -95,7 +95,7 @@ func (r *Remote) Fetch(o *FetchOptions) (err error) {
return NoErrAlreadyUpToDate
}
- req, err := r.buildRequest(r.s.ReferenceStorage(), o, refs)
+ req, err := r.buildRequest(r.s, o, refs)
if err != nil {
return err
}
@@ -139,7 +139,7 @@ func (r *Remote) getWantedReferences(spec []config.RefSpec) ([]*core.Reference,
}
}
- _, err := r.s.ObjectStorage().Get(core.CommitObject, ref.Hash())
+ _, err := r.s.Object(core.CommitObject, ref.Hash())
if err == core.ErrObjectNotFound {
refs = append(refs, ref)
return nil
@@ -150,7 +150,7 @@ func (r *Remote) getWantedReferences(spec []config.RefSpec) ([]*core.Reference,
}
func (r *Remote) buildRequest(
- s core.ReferenceStorage, o *FetchOptions, refs []*core.Reference,
+ s core.ReferenceStorer, o *FetchOptions, refs []*core.Reference,
) (*common.GitUploadPackRequest, error) {
req := &common.GitUploadPackRequest{}
req.Depth = o.Depth
@@ -159,7 +159,7 @@ func (r *Remote) buildRequest(
req.Want(ref.Hash())
}
- i, err := s.Iter()
+ i, err := s.IterReferences()
if err != nil {
return nil, err
}
@@ -177,9 +177,8 @@ func (r *Remote) buildRequest(
}
func (r *Remote) updateObjectStorage(reader io.Reader) error {
- s := r.s.ObjectStorage()
- if sw, ok := s.(core.ObjectStorageWrite); ok {
- w, err := sw.Writer()
+ if sw, ok := r.s.(core.PackfileWriter); ok {
+ w, err := sw.PackfileWriter()
if err != nil {
return err
}
@@ -190,7 +189,7 @@ func (r *Remote) updateObjectStorage(reader io.Reader) error {
}
stream := packfile.NewScanner(reader)
- d, err := packfile.NewDecoder(stream, s)
+ d, err := packfile.NewDecoder(stream, r.s)
if err != nil {
return err
}
@@ -212,7 +211,7 @@ func (r *Remote) updateLocalReferenceStorage(specs []config.RefSpec, refs []*cor
name := spec.Dst(ref.Name())
n := core.NewHashReference(name, ref.Hash())
- if err := r.s.ReferenceStorage().Set(n); err != nil {
+ if err := r.s.SetReference(n); err != nil {
return err
}
}
@@ -227,13 +226,12 @@ func (r *Remote) buildFetchedTags() error {
return err
}
- os := r.s.ObjectStorage()
return iter.ForEach(func(ref *core.Reference) error {
if !ref.IsTag() {
return nil
}
- _, err := os.Get(core.AnyObject, ref.Hash())
+ _, err := r.s.Object(core.AnyObject, ref.Hash())
if err == core.ErrObjectNotFound {
return nil
}
@@ -242,7 +240,7 @@ func (r *Remote) buildFetchedTags() error {
return err
}
- return r.s.ReferenceStorage().Set(ref)
+ return r.s.SetReference(ref)
})
}
@@ -257,12 +255,12 @@ func (r *Remote) Ref(name core.ReferenceName, resolved bool) (*core.Reference, e
return core.ResolveReference(r.upInfo.Refs, name)
}
- return r.upInfo.Refs.Get(name)
+ return r.upInfo.Refs.Reference(name)
}
// Refs returns a map with all the References
func (r *Remote) Refs() (core.ReferenceIter, error) {
- return r.upInfo.Refs.Iter()
+ return r.upInfo.Refs.IterReferences()
}
// Disconnect from the remote and save the config
diff --git a/remote_test.go b/remote_test.go
index 37539af..04167cd 100644
--- a/remote_test.go
+++ b/remote_test.go
@@ -1,6 +1,7 @@
package git
import (
+ "io"
"io/ioutil"
"os"
@@ -80,7 +81,7 @@ func (s *RemoteSuite) TestFetch(c *C) {
})
c.Assert(err, IsNil)
- c.Assert(sto.ObjectStorage().(*memory.ObjectStorage).Objects, HasLen, 31)
+ c.Assert(sto.Objects, HasLen, 31)
expectedRefs := []*core.Reference{
core.NewReferenceFromStrings("refs/remotes/origin/master", "6ecf0ef2c2dffb796033e5a02219af86ec6584e5"),
@@ -89,22 +90,33 @@ func (s *RemoteSuite) TestFetch(c *C) {
}
for _, exp := range expectedRefs {
- r, _ := sto.ReferenceStorage().Get(exp.Name())
+ r, _ := sto.Reference(exp.Name())
c.Assert(exp.String(), Equals, r.String())
}
}
-func (s *RemoteSuite) TestFetchObjectStorageWriter(c *C) {
+type mockPackfileWriter struct {
+ Storer
+ PackfileWriterCalled bool
+}
+
+func (m *mockPackfileWriter) PackfileWriter() (io.WriteCloser, error) {
+ m.PackfileWriterCalled = true
+ return m.Storer.(core.PackfileWriter).PackfileWriter()
+}
+
+func (s *RemoteSuite) TestFetchWithPackfileWriter(c *C) {
dir, err := ioutil.TempDir("", "fetch")
c.Assert(err, IsNil)
defer os.RemoveAll(dir) // clean up
- var sto Storage
- sto, err = filesystem.NewStorage(osfs.New(dir))
+ fss, err := filesystem.NewStorage(osfs.New(dir))
c.Assert(err, IsNil)
- r := newRemote(sto, &config.RemoteConfig{Name: "foo", URL: RepositoryFixture})
+ mock := &mockPackfileWriter{Storer: fss}
+
+ r := newRemote(mock, &config.RemoteConfig{Name: "foo", URL: RepositoryFixture})
r.upSrv = &MockGitUploadPackService{}
c.Assert(r.Connect(), IsNil)
@@ -116,14 +128,16 @@ func (s *RemoteSuite) TestFetchObjectStorageWriter(c *C) {
c.Assert(err, IsNil)
var count int
- iter, err := sto.ObjectStorage().Iter(core.AnyObject)
+ iter, err := mock.IterObjects(core.AnyObject)
c.Assert(err, IsNil)
iter.ForEach(func(core.Object) error {
count++
return nil
})
+
c.Assert(count, Equals, 31)
+ c.Assert(mock.PackfileWriterCalled, Equals, true)
}
func (s *RemoteSuite) TestFetchNoErrAlreadyUpToDate(c *C) {
diff --git a/repository.go b/repository.go
index 553703a..899127b 100644
--- a/repository.go
+++ b/repository.go
@@ -15,12 +15,14 @@ var (
ErrObjectNotFound = errors.New("object not found")
ErrInvalidReference = errors.New("invalid reference, should be a tag or a branch")
ErrRepositoryNonEmpty = errors.New("repository non empty")
+ ErrRemoteNotFound = errors.New("remote not found")
+ ErrRemoteExists = errors.New("remote already exists")
)
// Repository giturl string, auth common.AuthMethod repository struct
type Repository struct {
r map[string]*Remote
- s Storage
+ s Storer
}
// NewMemoryRepository creates a new repository, backed by a memory.Storage
@@ -42,7 +44,7 @@ func NewFilesystemRepository(path string) (*Repository, error) {
}
// NewRepository creates a new repository with the given Storage
-func NewRepository(s Storage) (*Repository, error) {
+func NewRepository(s Storer) (*Repository, error) {
return &Repository{
s: s,
r: make(map[string]*Remote, 0),
@@ -51,24 +53,32 @@ func NewRepository(s Storage) (*Repository, error) {
// Remote return a remote if exists
func (r *Repository) Remote(name string) (*Remote, error) {
- c, err := r.s.ConfigStorage().Remote(name)
+ cfg, err := r.s.Config()
if err != nil {
return nil, err
}
+ c, ok := cfg.Remotes[name]
+ if !ok {
+ return nil, ErrRemoteNotFound
+ }
+
return newRemote(r.s, c), nil
}
// Remotes return all the remotes
func (r *Repository) Remotes() ([]*Remote, error) {
- config, err := r.s.ConfigStorage().Remotes()
+ cfg, err := r.s.Config()
if err != nil {
return nil, err
}
- remotes := make([]*Remote, len(config))
- for i, c := range config {
+ remotes := make([]*Remote, len(cfg.Remotes))
+
+ var i int
+ for _, c := range cfg.Remotes {
remotes[i] = newRemote(r.s, c)
+ i++
}
return remotes, nil
@@ -81,16 +91,33 @@ func (r *Repository) CreateRemote(c *config.RemoteConfig) (*Remote, error) {
}
remote := newRemote(r.s, c)
- if err := r.s.ConfigStorage().SetRemote(c); err != nil {
+
+ cfg, err := r.s.Config()
+ if err != nil {
return nil, err
}
- return remote, nil
+ if _, ok := cfg.Remotes[c.Name]; ok {
+ return nil, ErrRemoteExists
+ }
+
+ cfg.Remotes[c.Name] = c
+ return remote, r.s.SetConfig(cfg)
}
// DeleteRemote delete a remote from the repository and delete the config
func (r *Repository) DeleteRemote(name string) error {
- return r.s.ConfigStorage().DeleteRemote(name)
+ cfg, err := r.s.Config()
+ if err != nil {
+ return err
+ }
+
+ if _, ok := cfg.Remotes[name]; !ok {
+ return ErrRemoteNotFound
+ }
+
+ delete(cfg.Remotes, name)
+ return r.s.SetConfig(cfg)
}
// Clone clones a remote repository
@@ -145,35 +172,42 @@ const refspecSingleBranch = "+refs/heads/%s:refs/remotes/%s/%[1]s"
func (r *Repository) updateRemoteConfig(
remote *Remote, o *CloneOptions, c *config.RemoteConfig,
) error {
- if o.SingleBranch {
- head, err := core.ResolveReference(remote.Info().Refs, o.ReferenceName)
- if err != nil {
- return err
- }
+ if !o.SingleBranch {
+ return nil
+ }
- c.Fetch = []config.RefSpec{
- config.RefSpec(fmt.Sprintf(refspecSingleBranch, head.Name().Short(), c.Name)),
- }
+ head, err := core.ResolveReference(remote.Info().Refs, o.ReferenceName)
+ if err != nil {
+ return err
+ }
+
+ c.Fetch = []config.RefSpec{
+ config.RefSpec(fmt.Sprintf(refspecSingleBranch, head.Name().Short(), c.Name)),
+ }
- return r.s.ConfigStorage().SetRemote(c)
+ cfg, err := r.s.Config()
+ if err != nil {
+ return err
}
- return nil
+ cfg.Remotes[c.Name] = c
+ return r.s.SetConfig(cfg)
+
}
func (r *Repository) createReferences(ref *core.Reference) error {
if !ref.IsBranch() {
// detached HEAD mode
head := core.NewHashReference(core.HEAD, ref.Hash())
- return r.s.ReferenceStorage().Set(head)
+ return r.s.SetReference(head)
}
- if err := r.s.ReferenceStorage().Set(ref); err != nil {
+ if err := r.s.SetReference(ref); err != nil {
return err
}
head := core.NewSymbolicReference(core.HEAD, ref.Name())
- return r.s.ReferenceStorage().Set(head)
+ return r.s.SetReference(head)
}
// IsEmpty returns true if the repository is empty
@@ -241,7 +275,7 @@ func (r *Repository) Commit(h core.Hash) (*Commit, error) {
// Commits decode the objects into commits
func (r *Repository) Commits() (*CommitIter, error) {
- iter, err := r.s.ObjectStorage().Iter(core.CommitObject)
+ iter, err := r.s.IterObjects(core.CommitObject)
if err != nil {
return nil, err
}
@@ -261,7 +295,7 @@ func (r *Repository) Tree(h core.Hash) (*Tree, error) {
// Trees decodes the objects into trees
func (r *Repository) Trees() (*TreeIter, error) {
- iter, err := r.s.ObjectStorage().Iter(core.TreeObject)
+ iter, err := r.s.IterObjects(core.TreeObject)
if err != nil {
return nil, err
}
@@ -281,7 +315,7 @@ func (r *Repository) Blob(h core.Hash) (*Blob, error) {
// Blobs decodes the objects into blobs
func (r *Repository) Blobs() (*BlobIter, error) {
- iter, err := r.s.ObjectStorage().Iter(core.BlobObject)
+ iter, err := r.s.IterObjects(core.BlobObject)
if err != nil {
return nil, err
}
@@ -302,7 +336,7 @@ func (r *Repository) Tag(h core.Hash) (*Tag, error) {
// Tags returns a TagIter that can step through all of the annotated tags
// in the repository.
func (r *Repository) Tags() (*TagIter, error) {
- iter, err := r.s.ObjectStorage().Iter(core.TagObject)
+ iter, err := r.s.IterObjects(core.TagObject)
if err != nil {
return nil, err
}
@@ -312,7 +346,7 @@ func (r *Repository) Tags() (*TagIter, error) {
// Object returns an object with the given hash.
func (r *Repository) Object(t core.ObjectType, h core.Hash) (Object, error) {
- obj, err := r.s.ObjectStorage().Get(t, h)
+ obj, err := r.s.Object(t, h)
if err != nil {
if err == core.ErrObjectNotFound {
return nil, ErrObjectNotFound
@@ -341,7 +375,7 @@ func (r *Repository) Object(t core.ObjectType, h core.Hash) (Object, error) {
// Objects returns an ObjectIter that can step through all of the annotated tags
// in the repository.
func (r *Repository) Objects() (*ObjectIter, error) {
- iter, err := r.s.ObjectStorage().Iter(core.AnyObject)
+ iter, err := r.s.IterObjects(core.AnyObject)
if err != nil {
return nil, err
}
@@ -351,19 +385,19 @@ func (r *Repository) Objects() (*ObjectIter, error) {
// Head returns the reference where HEAD is pointing
func (r *Repository) Head() (*core.Reference, error) {
- return core.ResolveReference(r.s.ReferenceStorage(), core.HEAD)
+ return core.ResolveReference(r.s, core.HEAD)
}
// Ref returns the Hash pointing the given refName
func (r *Repository) Ref(name core.ReferenceName, resolved bool) (*core.Reference, error) {
if resolved {
- return core.ResolveReference(r.s.ReferenceStorage(), name)
+ return core.ResolveReference(r.s, name)
}
- return r.s.ReferenceStorage().Get(name)
+ return r.s.Reference(name)
}
// Refs returns a map with all the References
func (r *Repository) Refs() (core.ReferenceIter, error) {
- return r.s.ReferenceStorage().Iter()
+ return r.s.IterReferences()
}
diff --git a/repository_test.go b/repository_test.go
index b67e31d..6c7fe4f 100644
--- a/repository_test.go
+++ b/repository_test.go
@@ -56,7 +56,7 @@ func (s *RepositorySuite) TestDeleteRemote(c *C) {
c.Assert(err, IsNil)
alt, err := r.Remote("foo")
- c.Assert(err, Equals, config.ErrRemoteConfigNotFound)
+ c.Assert(err, Equals, ErrRemoteNotFound)
c.Assert(alt, IsNil)
}
@@ -219,7 +219,7 @@ func (s *RepositorySuite) TestPull(c *C) {
c.Assert(err, IsNil)
c.Assert(branch.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
- storage := r.s.ObjectStorage().(*memory.ObjectStorage)
+ storage := r.s.(*memory.Storage)
c.Assert(storage.Objects, HasLen, 31)
r.CreateRemote(&config.RemoteConfig{
diff --git a/storage/filesystem/config.go b/storage/filesystem/config.go
index b32265f..4b47937 100644
--- a/storage/filesystem/config.go
+++ b/storage/filesystem/config.go
@@ -18,70 +18,24 @@ type ConfigStorage struct {
dir *dotgit.DotGit
}
-func (c *ConfigStorage) Remote(name string) (*config.RemoteConfig, error) {
- cfg, err := c.read()
- if err != nil {
- return nil, err
- }
-
- s := cfg.Section(remoteSection)
- if !s.HasSubsection(name) {
- return nil, config.ErrRemoteConfigNotFound
- }
+func (c *ConfigStorage) Config() (*config.Config, error) {
+ cfg := config.NewConfig()
- return parseRemote(s.Subsection(name)), nil
-}
-
-func (c *ConfigStorage) Remotes() ([]*config.RemoteConfig, error) {
- cfg, err := c.read()
+ ini, err := c.unmarshal()
if err != nil {
return nil, err
}
- remotes := []*config.RemoteConfig{}
- sect := cfg.Section(remoteSection)
+ sect := ini.Section(remoteSection)
for _, s := range sect.Subsections {
- remotes = append(remotes, parseRemote(s))
- }
-
- return remotes, nil
-}
-
-func (c *ConfigStorage) SetRemote(r *config.RemoteConfig) error {
- if err := r.Validate(); err != nil {
- return err
+ r := c.unmarshalRemote(s)
+ cfg.Remotes[r.Name] = r
}
- cfg, err := c.read()
- if err != nil {
- return err
- }
-
- s := cfg.Section(remoteSection).Subsection(r.Name)
- s.Name = r.Name
- if r.URL != "" {
- s.SetOption(urlKey, r.URL)
- }
- s.RemoveOption(fetchKey)
- for _, rs := range r.Fetch {
- s.AddOption(fetchKey, rs.String())
- }
-
- return c.write(cfg)
-}
-
-func (c *ConfigStorage) DeleteRemote(name string) error {
- cfg, err := c.read()
- if err != nil {
- return err
- }
-
- cfg = cfg.RemoveSubsection(remoteSection, name)
-
- return c.write(cfg)
+ return cfg, nil
}
-func (c *ConfigStorage) read() (*gitconfig.Config, error) {
+func (c *ConfigStorage) unmarshal() (*gitconfig.Config, error) {
cfg := gitconfig.New()
f, err := c.dir.Config()
@@ -103,23 +57,7 @@ func (c *ConfigStorage) read() (*gitconfig.Config, error) {
return cfg, nil
}
-func (c *ConfigStorage) write(cfg *gitconfig.Config) error {
- f, err := c.dir.ConfigWriter()
- if err != nil {
- return err
- }
-
- e := gitconfig.NewEncoder(f)
- err = e.Encode(cfg)
- if err != nil {
- f.Close()
- return err
- }
-
- return f.Close()
-}
-
-func parseRemote(s *gitconfig.Subsection) *config.RemoteConfig {
+func (c *ConfigStorage) unmarshalRemote(s *gitconfig.Subsection) *config.RemoteConfig {
fetch := []config.RefSpec{}
for _, f := range s.Options.GetAll(fetchKey) {
rs := config.RefSpec(f)
@@ -134,3 +72,47 @@ func parseRemote(s *gitconfig.Subsection) *config.RemoteConfig {
Fetch: fetch,
}
}
+
+func (c *ConfigStorage) SetConfig(cfg *config.Config) error {
+ if err := cfg.Validate(); err != nil {
+ return err
+ }
+
+ ini, err := c.unmarshal()
+ if err != nil {
+ return err
+ }
+
+ s := ini.Section(remoteSection)
+ s.Subsections = make(gitconfig.Subsections, len(cfg.Remotes))
+
+ var i int
+ for _, r := range cfg.Remotes {
+ s.Subsections[i] = c.marshalRemote(r)
+ i++
+ }
+
+ return c.marshal(ini)
+}
+
+func (c *ConfigStorage) marshal(ini *gitconfig.Config) error {
+ f, err := c.dir.ConfigWriter()
+ if err != nil {
+ return err
+ }
+
+ defer f.Close()
+
+ e := gitconfig.NewEncoder(f)
+ return e.Encode(ini)
+}
+
+func (c *ConfigStorage) marshalRemote(r *config.RemoteConfig) *gitconfig.Subsection {
+ s := &gitconfig.Subsection{Name: r.Name}
+ s.AddOption(urlKey, r.URL)
+ for _, rs := range r.Fetch {
+ s.AddOption(fetchKey, rs.String())
+ }
+
+ return s
+}
diff --git a/storage/filesystem/config_test.go b/storage/filesystem/config_test.go
index 2eb0ab9..b86eaee 100644
--- a/storage/filesystem/config_test.go
+++ b/storage/filesystem/config_test.go
@@ -4,7 +4,6 @@ import (
"io/ioutil"
stdos "os"
- "gopkg.in/src-d/go-git.v4/config"
"gopkg.in/src-d/go-git.v4/fixtures"
"gopkg.in/src-d/go-git.v4/storage/filesystem/internal/dotgit"
"gopkg.in/src-d/go-git.v4/utils/fs/os"
@@ -29,27 +28,20 @@ func (s *ConfigSuite) SetUpTest(c *C) {
s.path = tmp
}
-func (s *ConfigSuite) TestSetRemote(c *C) {
- cfg := &ConfigStorage{s.dir}
- err := cfg.SetRemote(&config.RemoteConfig{Name: "foo", URL: "foo"})
- c.Assert(err, IsNil)
-
- remote, err := cfg.Remote("foo")
- c.Assert(err, IsNil)
- c.Assert(remote.Name, Equals, "foo")
-}
-
func (s *ConfigSuite) TestRemotes(c *C) {
dir := dotgit.New(fixtures.Basic().ByTag(".git").One().DotGit())
- cfg := &ConfigStorage{dir}
+ storer := &ConfigStorage{dir}
- remotes, err := cfg.Remotes()
+ cfg, err := storer.Config()
c.Assert(err, IsNil)
+
+ remotes := cfg.Remotes
c.Assert(remotes, HasLen, 1)
- c.Assert(remotes[0].Name, Equals, "origin")
- c.Assert(remotes[0].URL, Equals, "https://github.com/git-fixtures/basic")
- c.Assert(remotes[0].Fetch, HasLen, 1)
- c.Assert(remotes[0].Fetch[0].String(), Equals, "+refs/heads/*:refs/remotes/origin/*")
+ remote := remotes["origin"]
+ c.Assert(remote.Name, Equals, "origin")
+ c.Assert(remote.URL, Equals, "https://github.com/git-fixtures/basic")
+ c.Assert(remote.Fetch, HasLen, 1)
+ c.Assert(remote.Fetch[0].String(), Equals, "+refs/heads/*:refs/remotes/origin/*")
}
func (s *ConfigSuite) TearDownTest(c *C) {
diff --git a/storage/filesystem/object.go b/storage/filesystem/object.go
index 6dbeae9..f780183 100644
--- a/storage/filesystem/object.go
+++ b/storage/filesystem/object.go
@@ -13,25 +13,17 @@ import (
"gopkg.in/src-d/go-git.v4/utils/fs"
)
-// ObjectStorage is an implementation of core.ObjectStorage that stores
-// data on disk in the standard git format (this is, the .git directory).
-//
-// Zero values of this type are not safe to use, see the New function below.
-//
-// Currently only reads are supported, no writting.
-//
-// Also values from this type are not yet able to track changes on disk, this is,
-// Gitdir values will get outdated as soon as repositories change on disk.
type ObjectStorage struct {
dir *dotgit.DotGit
index map[core.Hash]index
}
-func newObjectStorage(dir *dotgit.DotGit) (*ObjectStorage, error) {
- s := &ObjectStorage{
+func newObjectStorage(dir *dotgit.DotGit) (ObjectStorage, error) {
+ s := ObjectStorage{
dir: dir,
index: make(map[core.Hash]index, 0),
}
+
return s, s.loadIdxFiles()
}
@@ -64,8 +56,7 @@ func (s *ObjectStorage) NewObject() core.Object {
return &core.MemoryObject{}
}
-// Writer method not supported on Memory storage
-func (s *ObjectStorage) Writer() (io.WriteCloser, error) {
+func (s *ObjectStorage) PackfileWriter() (io.WriteCloser, error) {
w, err := s.dir.NewObjectPack()
if err != nil {
return nil, err
@@ -82,7 +73,7 @@ func (s *ObjectStorage) Writer() (io.WriteCloser, error) {
}
// Set adds a new object to the storage.
-func (s *ObjectStorage) Set(o core.Object) (core.Hash, error) {
+func (s *ObjectStorage) SetObject(o core.Object) (core.Hash, error) {
if o.Type() == core.OFSDeltaObject || o.Type() == core.REFDeltaObject {
return core.ZeroHash, core.ErrInvalidType
}
@@ -114,7 +105,7 @@ func (s *ObjectStorage) Set(o core.Object) (core.Hash, error) {
// Get returns the object with the given hash, by searching for it in
// the packfile and the git object directories.
-func (s *ObjectStorage) Get(t core.ObjectType, h core.Hash) (core.Object, error) {
+func (s *ObjectStorage) Object(t core.ObjectType, h core.Hash) (core.Object, error) {
obj, err := s.getFromUnpacked(h)
if err == core.ErrObjectNotFound {
obj, err = s.getFromPackfile(h)
@@ -183,7 +174,7 @@ func (s *ObjectStorage) getFromPackfile(h core.Hash) (core.Object, error) {
defer f.Close()
p := packfile.NewScanner(f)
- d, err := packfile.NewDecoder(p, memory.NewStorage().ObjectStorage())
+ d, err := packfile.NewDecoder(p, memory.NewStorage())
if err != nil {
return nil, err
}
@@ -204,7 +195,7 @@ func (s *ObjectStorage) findObjectInPackfile(h core.Hash) (core.Hash, int64) {
// Iter returns an iterator for all the objects in the packfile with the
// given type.
-func (s *ObjectStorage) Iter(t core.ObjectType) (core.ObjectIter, error) {
+func (s *ObjectStorage) IterObjects(t core.ObjectType) (core.ObjectIter, error) {
objects, err := s.dir.Objects()
if err != nil {
return nil, err
@@ -251,20 +242,6 @@ func (s *ObjectStorage) buildPackfileIters(
return iters, nil
}
-// Begin opens a new transaction. However, this implementation is not
-// transactional, so Commit and Rollback have no effect.
-func (o *ObjectStorage) Begin() core.TxObjectStorage {
- return o
-}
-
-func (tx *ObjectStorage) Commit() error {
- return nil
-}
-
-func (tx *ObjectStorage) Rollback() error {
- return nil
-}
-
type index map[core.Hash]int64
func (i index) Decode(r io.Reader) error {
@@ -299,7 +276,7 @@ func newPackfileIter(f fs.File, t core.ObjectType, seen map[core.Hash]bool) (cor
return nil, err
}
- d, err := packfile.NewDecoder(s, memory.NewStorage().ObjectStorage())
+ d, err := packfile.NewDecoder(s, memory.NewStorage())
if err != nil {
return nil, err
}
diff --git a/storage/filesystem/object_test.go b/storage/filesystem/object_test.go
index 0136e54..38e4b6d 100644
--- a/storage/filesystem/object_test.go
+++ b/storage/filesystem/object_test.go
@@ -20,7 +20,7 @@ func (s *FsSuite) TestGetFromObjectFile(c *C) {
c.Assert(err, IsNil)
expected := core.NewHash("f3dfe29d268303fc6e1bbce268605fc99573406e")
- obj, err := o.Get(core.AnyObject, expected)
+ obj, err := o.Object(core.AnyObject, expected)
c.Assert(err, IsNil)
c.Assert(obj.Hash(), Equals, expected)
}
@@ -32,7 +32,7 @@ func (s *FsSuite) TestGetFromPackfile(c *C) {
c.Assert(err, IsNil)
expected := core.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
- obj, err := o.Get(core.AnyObject, expected)
+ obj, err := o.Object(core.AnyObject, expected)
c.Assert(err, IsNil)
c.Assert(obj.Hash(), Equals, expected)
})
@@ -60,7 +60,7 @@ func (s *FsSuite) TestIter(c *C) {
o, err := newObjectStorage(dotgit.New(fs))
c.Assert(err, IsNil)
- iter, err := o.Iter(core.AnyObject)
+ iter, err := o.IterObjects(core.AnyObject)
c.Assert(err, IsNil)
var count int32
@@ -80,7 +80,7 @@ func (s *FsSuite) TestIterWithType(c *C) {
o, err := newObjectStorage(dotgit.New(fs))
c.Assert(err, IsNil)
- iter, err := o.Iter(core.CommitObject)
+ iter, err := o.IterObjects(core.CommitObject)
c.Assert(err, IsNil)
err = iter.ForEach(func(o core.Object) error {
diff --git a/storage/filesystem/reference.go b/storage/filesystem/reference.go
index b2aa6d9..0015859 100644
--- a/storage/filesystem/reference.go
+++ b/storage/filesystem/reference.go
@@ -9,15 +9,15 @@ type ReferenceStorage struct {
dir *dotgit.DotGit
}
-func (r *ReferenceStorage) Set(ref *core.Reference) error {
+func (r *ReferenceStorage) SetReference(ref *core.Reference) error {
return r.dir.SetRef(ref)
}
-func (r *ReferenceStorage) Get(n core.ReferenceName) (*core.Reference, error) {
+func (r *ReferenceStorage) Reference(n core.ReferenceName) (*core.Reference, error) {
return r.dir.Ref(n)
}
-func (r *ReferenceStorage) Iter() (core.ReferenceIter, error) {
+func (r *ReferenceStorage) IterReferences() (core.ReferenceIter, error) {
refs, err := r.dir.Refs()
if err != nil {
return nil, err
diff --git a/storage/filesystem/storage.go b/storage/filesystem/storage.go
index d39d6e4..7e05cd3 100644
--- a/storage/filesystem/storage.go
+++ b/storage/filesystem/storage.go
@@ -2,21 +2,20 @@
package filesystem
import (
- "gopkg.in/src-d/go-git.v4/config"
- "gopkg.in/src-d/go-git.v4/core"
"gopkg.in/src-d/go-git.v4/storage/filesystem/internal/dotgit"
"gopkg.in/src-d/go-git.v4/utils/fs"
)
+// Storage is an implementation of git.Storer that stores data on disk in the
+// standard git format (this is, the .git directory). Zero values of this type
+// are not safe to use, see the NewStorage function below.
type Storage struct {
- dir *dotgit.DotGit
- fs fs.Filesystem
-
- o *ObjectStorage
- r *ReferenceStorage
- c *ConfigStorage
+ ObjectStorage
+ ReferenceStorage
+ ConfigStorage
}
+// NewStorage returns a new Storage backed by a given `fs.Filesystem`
func NewStorage(fs fs.Filesystem) (*Storage, error) {
dir := dotgit.New(fs)
o, err := newObjectStorage(dir)
@@ -24,27 +23,9 @@ func NewStorage(fs fs.Filesystem) (*Storage, error) {
return nil, err
}
- return &Storage{dir: dir, fs: fs, o: o}, nil
-}
-
-func (s *Storage) ObjectStorage() core.ObjectStorage {
- return s.o
-}
-
-func (s *Storage) ReferenceStorage() core.ReferenceStorage {
- if s.r != nil {
- return s.r
- }
-
- s.r = &ReferenceStorage{dir: s.dir}
- return s.r
-}
-
-func (s *Storage) ConfigStorage() config.ConfigStorage {
- if s.c != nil {
- return s.c
- }
-
- s.c = &ConfigStorage{dir: s.dir}
- return s.c
+ return &Storage{
+ ObjectStorage: o,
+ ReferenceStorage: ReferenceStorage{dir: dir},
+ ConfigStorage: ConfigStorage{dir: dir},
+ }, nil
}
diff --git a/storage/filesystem/storage_test.go b/storage/filesystem/storage_test.go
index f55452d..c24d5d5 100644
--- a/storage/filesystem/storage_test.go
+++ b/storage/filesystem/storage_test.go
@@ -18,20 +18,8 @@ type StorageSuite struct {
var _ = Suite(&StorageSuite{})
func (s *StorageSuite) SetUpTest(c *C) {
- path := c.MkDir()
- storage, err := NewStorage(os.New(path))
+ storage, err := NewStorage(os.New(c.MkDir()))
c.Assert(err, IsNil)
- s.BaseStorageSuite = test.NewBaseStorageSuite(
- storage.ObjectStorage(),
- storage.ReferenceStorage(),
- storage.ConfigStorage(),
- )
-}
-
-func (s *StorageSuite) TestTxObjectStorageSetAndCommit(c *C) {
- c.Skip("tx not supported")
-}
-func (s *StorageSuite) TestTxObjectStorageSetAndRollback(c *C) {
- c.Skip("tx not supported")
+ s.BaseStorageSuite = test.NewBaseStorageSuite(storage)
}
diff --git a/storage/memory/storage.go b/storage/memory/storage.go
index 97e87c8..8141cfc 100644
--- a/storage/memory/storage.go
+++ b/storage/memory/storage.go
@@ -10,96 +10,52 @@ import (
var ErrUnsupportedObjectType = fmt.Errorf("unsupported object type")
-// Storage in memory storage system
+// Storage is an implementation of git.Storer that stores data on memory, being
+// ephemeral. The use of this storage should be done in controlled envoriments,
+// since the representation in memory of some repository can fill the machine
+// memory. in the other hand this storage has the best performance.
type Storage struct {
- c *ConfigStorage
- o *ObjectStorage
- r *ReferenceStorage
+ ConfigStorage
+ ObjectStorage
+ ReferenceStorage
}
-// NewStorage returns a new Storage
+// NewStorage returns a new Storage base on memory
func NewStorage() *Storage {
- return &Storage{}
-}
-
-// ConfigStorage return the ConfigStorage, if not exists create a new one
-func (s *Storage) ConfigStorage() config.ConfigStorage {
- if s.c != nil {
- return s.c
- }
-
- s.c = &ConfigStorage{
- RemotesConfig: make(map[string]*config.RemoteConfig),
- }
-
- return s.c
-}
-
-// ObjectStorage returns the ObjectStorage, if not exists creates a new one
-func (s *Storage) ObjectStorage() core.ObjectStorage {
- if s.o != nil {
- return s.o
- }
-
- s.o = &ObjectStorage{
- Objects: make(map[core.Hash]core.Object, 0),
- Commits: make(map[core.Hash]core.Object, 0),
- Trees: make(map[core.Hash]core.Object, 0),
- Blobs: make(map[core.Hash]core.Object, 0),
- Tags: make(map[core.Hash]core.Object, 0),
+ return &Storage{
+ ReferenceStorage: make(ReferenceStorage, 0),
+ ConfigStorage: ConfigStorage{},
+ ObjectStorage: ObjectStorage{
+ Objects: make(map[core.Hash]core.Object, 0),
+ Commits: make(map[core.Hash]core.Object, 0),
+ Trees: make(map[core.Hash]core.Object, 0),
+ Blobs: make(map[core.Hash]core.Object, 0),
+ Tags: make(map[core.Hash]core.Object, 0),
+ },
}
-
- return s.o
-}
-
-// ReferenceStorage returns the ReferenceStorage if not exists creates a new one
-func (s *Storage) ReferenceStorage() core.ReferenceStorage {
- if s.r != nil {
- return s.r
- }
-
- r := make(ReferenceStorage, 0)
- s.r = &r
-
- return s.r
}
type ConfigStorage struct {
- RemotesConfig map[string]*config.RemoteConfig
-}
-
-func (c *ConfigStorage) Remote(name string) (*config.RemoteConfig, error) {
- r, ok := c.RemotesConfig[name]
- if ok {
- return r, nil
- }
-
- return nil, config.ErrRemoteConfigNotFound
+ config *config.Config
}
-func (c *ConfigStorage) Remotes() ([]*config.RemoteConfig, error) {
- var o []*config.RemoteConfig
- for _, r := range c.RemotesConfig {
- o = append(o, r)
- }
-
- return o, nil
-}
-func (c *ConfigStorage) SetRemote(r *config.RemoteConfig) error {
- if err := r.Validate(); err != nil {
+func (c *ConfigStorage) SetConfig(cfg *config.Config) error {
+ if err := cfg.Validate(); err != nil {
return err
}
- c.RemotesConfig[r.Name] = r
+ c.config = cfg
return nil
}
-func (c *ConfigStorage) DeleteRemote(name string) error {
- delete(c.RemotesConfig, name)
- return nil
+func (c *ConfigStorage) Config() (*config.Config, error) {
+ if c.config == nil {
+ c.config = config.NewConfig()
+ }
+
+ return c.config, nil
}
-// ObjectStorage is the implementation of core.ObjectStorage for memory.Object
type ObjectStorage struct {
Objects map[core.Hash]core.Object
Commits map[core.Hash]core.Object
@@ -108,13 +64,11 @@ type ObjectStorage struct {
Tags map[core.Hash]core.Object
}
-// NewObject creates a new MemoryObject
func (o *ObjectStorage) NewObject() core.Object {
return &core.MemoryObject{}
}
-// Set stores an object, the object should be properly filled before set it.
-func (o *ObjectStorage) Set(obj core.Object) (core.Hash, error) {
+func (o *ObjectStorage) SetObject(obj core.Object) (core.Hash, error) {
h := obj.Hash()
o.Objects[h] = obj
@@ -134,8 +88,7 @@ func (o *ObjectStorage) Set(obj core.Object) (core.Hash, error) {
return h, nil
}
-// Get returns a object with the given hash
-func (o *ObjectStorage) Get(t core.ObjectType, h core.Hash) (core.Object, error) {
+func (o *ObjectStorage) Object(t core.ObjectType, h core.Hash) (core.Object, error) {
obj, ok := o.Objects[h]
if !ok || (core.AnyObject != t && obj.Type() != t) {
return nil, core.ErrObjectNotFound
@@ -144,8 +97,7 @@ func (o *ObjectStorage) Get(t core.ObjectType, h core.Hash) (core.Object, error)
return obj, nil
}
-// Iter returns a core.ObjectIter for the given core.ObjectTybe
-func (o *ObjectStorage) Iter(t core.ObjectType) (core.ObjectIter, error) {
+func (o *ObjectStorage) IterObjects(t core.ObjectType) (core.ObjectIter, error) {
var series []core.Object
switch t {
case core.AnyObject:
@@ -171,7 +123,7 @@ func flattenObjectMap(m map[core.Hash]core.Object) []core.Object {
return objects
}
-func (o *ObjectStorage) Begin() core.TxObjectStorage {
+func (o *ObjectStorage) Begin() core.Transaction {
return &TxObjectStorage{
Storage: o,
Objects: make(map[core.Hash]core.Object, 0),
@@ -183,14 +135,14 @@ type TxObjectStorage struct {
Objects map[core.Hash]core.Object
}
-func (tx *TxObjectStorage) Set(obj core.Object) (core.Hash, error) {
+func (tx *TxObjectStorage) SetObject(obj core.Object) (core.Hash, error) {
h := obj.Hash()
tx.Objects[h] = obj
return h, nil
}
-func (tx *TxObjectStorage) Get(t core.ObjectType, h core.Hash) (core.Object, error) {
+func (tx *TxObjectStorage) Object(t core.ObjectType, h core.Hash) (core.Object, error) {
obj, ok := tx.Objects[h]
if !ok || (core.AnyObject != t && obj.Type() != t) {
return nil, core.ErrObjectNotFound
@@ -202,7 +154,7 @@ func (tx *TxObjectStorage) Get(t core.ObjectType, h core.Hash) (core.Object, err
func (tx *TxObjectStorage) Commit() error {
for h, obj := range tx.Objects {
delete(tx.Objects, h)
- if _, err := tx.Storage.Set(obj); err != nil {
+ if _, err := tx.Storage.SetObject(obj); err != nil {
return err
}
}
@@ -217,8 +169,7 @@ func (tx *TxObjectStorage) Rollback() error {
type ReferenceStorage map[core.ReferenceName]*core.Reference
-// Set stores a reference.
-func (r ReferenceStorage) Set(ref *core.Reference) error {
+func (r ReferenceStorage) SetReference(ref *core.Reference) error {
if ref != nil {
r[ref.Name()] = ref
}
@@ -226,8 +177,7 @@ func (r ReferenceStorage) Set(ref *core.Reference) error {
return nil
}
-// Get returns a stored reference with the given name
-func (r ReferenceStorage) Get(n core.ReferenceName) (*core.Reference, error) {
+func (r ReferenceStorage) Reference(n core.ReferenceName) (*core.Reference, error) {
ref, ok := r[n]
if !ok {
return nil, core.ErrReferenceNotFound
@@ -236,8 +186,7 @@ func (r ReferenceStorage) Get(n core.ReferenceName) (*core.Reference, error) {
return ref, nil
}
-// Iter returns a core.ReferenceIter
-func (r ReferenceStorage) Iter() (core.ReferenceIter, error) {
+func (r ReferenceStorage) IterReferences() (core.ReferenceIter, error) {
var refs []*core.Reference
for _, ref := range r {
refs = append(refs, ref)
diff --git a/storage/memory/storage_test.go b/storage/memory/storage_test.go
index e1d5a33..ee8fa93 100644
--- a/storage/memory/storage_test.go
+++ b/storage/memory/storage_test.go
@@ -16,34 +16,5 @@ type StorageSuite struct {
var _ = Suite(&StorageSuite{})
func (s *StorageSuite) SetUpTest(c *C) {
- storage := NewStorage()
- s.BaseStorageSuite = test.NewBaseStorageSuite(
- storage.ObjectStorage(),
- storage.ReferenceStorage(),
- storage.ConfigStorage(),
- )
-}
-
-func (s *StorageSuite) TestStorageObjectStorage(c *C) {
- storage := NewStorage()
- o := storage.ObjectStorage()
- e := storage.ObjectStorage()
-
- c.Assert(o == e, Equals, true)
-}
-
-func (s *StorageSuite) TestStorageReferenceStorage(c *C) {
- storage := NewStorage()
- o := storage.ReferenceStorage()
- e := storage.ReferenceStorage()
-
- c.Assert(o == e, Equals, true)
-}
-
-func (s *StorageSuite) TestStorageConfigStorage(c *C) {
- storage := NewStorage()
- o := storage.ConfigStorage()
- e := storage.ConfigStorage()
-
- c.Assert(o == e, Equals, true)
+ s.BaseStorageSuite = test.NewBaseStorageSuite(NewStorage())
}
diff --git a/storage/test/storage_suite.go b/storage/test/storage_suite.go
index 8686853..451528f 100644
--- a/storage/test/storage_suite.go
+++ b/storage/test/storage_suite.go
@@ -6,7 +6,6 @@ import (
"fmt"
"io"
"io/ioutil"
- "sort"
"gopkg.in/src-d/go-git.v4/config"
"gopkg.in/src-d/go-git.v4/core"
@@ -14,6 +13,12 @@ import (
. "gopkg.in/check.v1"
)
+type storer interface {
+ core.ObjectStorer
+ core.ReferenceStorer
+ config.ConfigStorer
+}
+
type TestObject struct {
Object core.Object
Hash string
@@ -21,19 +26,13 @@ type TestObject struct {
}
type BaseStorageSuite struct {
- ObjectStorage core.ObjectStorage
- ReferenceStorage core.ReferenceStorage
- ConfigStore config.ConfigStorage
+ Storer storer
validTypes []core.ObjectType
testObjects map[core.ObjectType]TestObject
}
-func NewBaseStorageSuite(
- os core.ObjectStorage,
- rs core.ReferenceStorage,
- cs config.ConfigStorage,
-) BaseStorageSuite {
+func NewBaseStorageSuite(s storer) BaseStorageSuite {
commit := &core.MemoryObject{}
commit.SetType(core.CommitObject)
tree := &core.MemoryObject{}
@@ -44,10 +43,7 @@ func NewBaseStorageSuite(
tag.SetType(core.TagObject)
return BaseStorageSuite{
- ObjectStorage: os,
- ReferenceStorage: rs,
- ConfigStore: cs,
-
+ Storer: s,
validTypes: []core.ObjectType{
core.CommitObject,
core.BlobObject,
@@ -62,19 +58,19 @@ func NewBaseStorageSuite(
}}
}
-func (s *BaseStorageSuite) TestObjectStorageSetAndGet(c *C) {
+func (s *BaseStorageSuite) TestSetObjectAndGetObject(c *C) {
for _, to := range s.testObjects {
comment := Commentf("failed for type %s", to.Type.String())
- h, err := s.ObjectStorage.Set(to.Object)
+ h, err := s.Storer.SetObject(to.Object)
c.Assert(err, IsNil)
c.Assert(h.String(), Equals, to.Hash, comment)
- o, err := s.ObjectStorage.Get(to.Type, h)
+ o, err := s.Storer.Object(to.Type, h)
c.Assert(err, IsNil)
c.Assert(objectEquals(o, to.Object), IsNil)
- o, err = s.ObjectStorage.Get(core.AnyObject, h)
+ o, err = s.Storer.Object(core.AnyObject, h)
c.Assert(err, IsNil)
c.Assert(objectEquals(o, to.Object), IsNil)
@@ -83,31 +79,31 @@ func (s *BaseStorageSuite) TestObjectStorageSetAndGet(c *C) {
continue
}
- o, err = s.ObjectStorage.Get(t, h)
+ o, err = s.Storer.Object(t, h)
c.Assert(o, IsNil)
c.Assert(err, Equals, core.ErrObjectNotFound)
}
}
}
-func (s *BaseStorageSuite) TestObjectStorageGetInvalid(c *C) {
- o := s.ObjectStorage.NewObject()
+func (s *BaseStorageSuite) TestSetObjectInvalid(c *C) {
+ o := s.Storer.NewObject()
o.SetType(core.REFDeltaObject)
- _, err := s.ObjectStorage.Set(o)
+ _, err := s.Storer.SetObject(o)
c.Assert(err, NotNil)
}
-func (s *BaseStorageSuite) TestObjectStorageIter(c *C) {
+func (s *BaseStorageSuite) TestStorerIter(c *C) {
for _, o := range s.testObjects {
- h, err := s.ObjectStorage.Set(o.Object)
+ h, err := s.Storer.SetObject(o.Object)
c.Assert(err, IsNil)
c.Assert(h, Equals, o.Object.Hash())
}
for _, t := range s.validTypes {
comment := Commentf("failed for type %s)", t.String())
- i, err := s.ObjectStorage.Iter(t)
+ i, err := s.Storer.IterObjects(t)
c.Assert(err, IsNil, comment)
o, err := i.Next()
@@ -119,7 +115,7 @@ func (s *BaseStorageSuite) TestObjectStorageIter(c *C) {
c.Assert(err, Equals, io.EOF, comment)
}
- i, err := s.ObjectStorage.Iter(core.AnyObject)
+ i, err := s.Storer.IterObjects(core.AnyObject)
c.Assert(err, IsNil)
foundObjects := []core.Object{}
@@ -141,15 +137,20 @@ func (s *BaseStorageSuite) TestObjectStorageIter(c *C) {
}
}
-func (s *BaseStorageSuite) TestTxObjectStorageSetAndCommit(c *C) {
- tx := s.ObjectStorage.Begin()
+func (s *BaseStorageSuite) TestObjectStorerTxSetObjectAndCommit(c *C) {
+ storer, ok := s.Storer.(core.Transactioner)
+ if !ok {
+ c.Skip("not a core.ObjectStorerTx")
+ }
+
+ tx := storer.Begin()
for _, o := range s.testObjects {
- h, err := tx.Set(o.Object)
+ h, err := tx.SetObject(o.Object)
c.Assert(err, IsNil)
c.Assert(h.String(), Equals, o.Hash)
}
- iter, err := s.ObjectStorage.Iter(core.AnyObject)
+ iter, err := s.Storer.IterObjects(core.AnyObject)
c.Assert(err, IsNil)
_, err = iter.Next()
c.Assert(err, Equals, io.EOF)
@@ -157,7 +158,7 @@ func (s *BaseStorageSuite) TestTxObjectStorageSetAndCommit(c *C) {
err = tx.Commit()
c.Assert(err, IsNil)
- iter, err = s.ObjectStorage.Iter(core.AnyObject)
+ iter, err = s.Storer.IterObjects(core.AnyObject)
c.Assert(err, IsNil)
var count int
@@ -169,29 +170,44 @@ func (s *BaseStorageSuite) TestTxObjectStorageSetAndCommit(c *C) {
c.Assert(count, Equals, 4)
}
-func (s *BaseStorageSuite) TestTxObjectStorageSetAndGet(c *C) {
- tx := s.ObjectStorage.Begin()
+func (s *BaseStorageSuite) TestObjectStorerTxSetObjectAndGetObject(c *C) {
+ storer, ok := s.Storer.(core.Transactioner)
+ if !ok {
+ c.Skip("not a core.ObjectStorerTx")
+ }
+
+ tx := storer.Begin()
for _, expected := range s.testObjects {
- h, err := tx.Set(expected.Object)
+ h, err := tx.SetObject(expected.Object)
c.Assert(err, IsNil)
c.Assert(h.String(), Equals, expected.Hash)
- o, err := tx.Get(expected.Type, core.NewHash(expected.Hash))
+ o, err := tx.Object(expected.Type, core.NewHash(expected.Hash))
c.Assert(o.Hash().String(), DeepEquals, expected.Hash)
}
}
-func (s *BaseStorageSuite) TestTxObjectStorageGetNotFound(c *C) {
- tx := s.ObjectStorage.Begin()
- o, err := tx.Get(core.AnyObject, core.ZeroHash)
+func (s *BaseStorageSuite) TestObjectStorerTxGetObjectNotFound(c *C) {
+ storer, ok := s.Storer.(core.Transactioner)
+ if !ok {
+ c.Skip("not a core.ObjectStorerTx")
+ }
+
+ tx := storer.Begin()
+ o, err := tx.Object(core.AnyObject, core.ZeroHash)
c.Assert(o, IsNil)
c.Assert(err, Equals, core.ErrObjectNotFound)
}
-func (s *BaseStorageSuite) TestTxObjectStorageSetAndRollback(c *C) {
- tx := s.ObjectStorage.Begin()
+func (s *BaseStorageSuite) TestObjectStorerTxSetObjectAndRollback(c *C) {
+ storer, ok := s.Storer.(core.Transactioner)
+ if !ok {
+ c.Skip("not a core.ObjectStorerTx")
+ }
+
+ tx := storer.Begin()
for _, o := range s.testObjects {
- h, err := tx.Set(o.Object)
+ h, err := tx.SetObject(o.Object)
c.Assert(err, IsNil)
c.Assert(h.String(), Equals, o.Hash)
}
@@ -199,41 +215,41 @@ func (s *BaseStorageSuite) TestTxObjectStorageSetAndRollback(c *C) {
err := tx.Rollback()
c.Assert(err, IsNil)
- iter, err := s.ObjectStorage.Iter(core.AnyObject)
+ iter, err := s.Storer.IterObjects(core.AnyObject)
c.Assert(err, IsNil)
_, err = iter.Next()
c.Assert(err, Equals, io.EOF)
}
-func (s *BaseStorageSuite) TestReferenceStorageSetAndGet(c *C) {
- err := s.ReferenceStorage.Set(
+func (s *BaseStorageSuite) TestSetReferenceAndGetReference(c *C) {
+ err := s.Storer.SetReference(
core.NewReferenceFromStrings("foo", "bc9968d75e48de59f0870ffb71f5e160bbbdcf52"),
)
c.Assert(err, IsNil)
- err = s.ReferenceStorage.Set(
+ err = s.Storer.SetReference(
core.NewReferenceFromStrings("bar", "482e0eada5de4039e6f216b45b3c9b683b83bfa"),
)
c.Assert(err, IsNil)
- e, err := s.ReferenceStorage.Get(core.ReferenceName("foo"))
+ e, err := s.Storer.Reference(core.ReferenceName("foo"))
c.Assert(err, IsNil)
c.Assert(e.Hash().String(), Equals, "bc9968d75e48de59f0870ffb71f5e160bbbdcf52")
}
-func (s *BaseStorageSuite) TestReferenceStorageGetNotFound(c *C) {
- r, err := s.ReferenceStorage.Get(core.ReferenceName("bar"))
+func (s *BaseStorageSuite) TestGetReferenceNotFound(c *C) {
+ r, err := s.Storer.Reference(core.ReferenceName("bar"))
c.Assert(err, Equals, core.ErrReferenceNotFound)
c.Assert(r, IsNil)
}
-func (s *BaseStorageSuite) TestReferenceStorageIter(c *C) {
- err := s.ReferenceStorage.Set(
+func (s *BaseStorageSuite) TestIterReferences(c *C) {
+ err := s.Storer.SetReference(
core.NewReferenceFromStrings("refs/foo", "bc9968d75e48de59f0870ffb71f5e160bbbdcf52"),
)
c.Assert(err, IsNil)
- i, err := s.ReferenceStorage.Iter()
+ i, err := s.Storer.IterReferences()
c.Assert(err, IsNil)
e, err := i.Next()
@@ -245,50 +261,27 @@ func (s *BaseStorageSuite) TestReferenceStorageIter(c *C) {
c.Assert(err, Equals, io.EOF)
}
-func (s *BaseStorageSuite) TestConfigStorageSetGetAndDelete(c *C) {
- err := s.ConfigStore.SetRemote(&config.RemoteConfig{
+func (s *BaseStorageSuite) TestSetConfigAndConfig(c *C) {
+ expected := config.NewConfig()
+ expected.Remotes["foo"] = &config.RemoteConfig{
Name: "foo",
URL: "http://foo/bar.git",
- })
-
- c.Assert(err, IsNil)
+ }
- r, err := s.ConfigStore.Remote("foo")
+ err := s.Storer.SetConfig(expected)
c.Assert(err, IsNil)
- c.Assert(r.Name, Equals, "foo")
- err = s.ConfigStore.DeleteRemote("foo")
+ cfg, err := s.Storer.Config()
c.Assert(err, IsNil)
-
- r, err = s.ConfigStore.Remote("foo")
- c.Assert(err, Equals, config.ErrRemoteConfigNotFound)
- c.Assert(r, IsNil)
-}
-
-func (s *BaseStorageSuite) TestConfigStorageSetInvalid(c *C) {
- err := s.ConfigStore.SetRemote(&config.RemoteConfig{})
- c.Assert(err, NotNil)
+ c.Assert(cfg, DeepEquals, expected)
}
-func (s *BaseStorageSuite) TestConfigStorageRemotes(c *C) {
- s.ConfigStore.SetRemote(&config.RemoteConfig{
- Name: "foo", URL: "http://foo/bar.git",
- })
-
- s.ConfigStore.SetRemote(&config.RemoteConfig{
- Name: "bar", URL: "http://foo/bar.git",
- })
+func (s *BaseStorageSuite) TestSetConfigInvalid(c *C) {
+ cfg := config.NewConfig()
+ cfg.Remotes["foo"] = &config.RemoteConfig{}
- r, err := s.ConfigStore.Remotes()
- c.Assert(err, IsNil)
- c.Assert(r, HasLen, 2)
-
- sorted := make([]string, 0, 2)
- sorted = append(sorted, r[0].Name)
- sorted = append(sorted, r[1].Name)
- sort.Strings(sorted)
- c.Assert(sorted[0], Equals, "bar")
- c.Assert(sorted[1], Equals, "foo")
+ err := s.Storer.SetConfig(cfg)
+ c.Assert(err, NotNil)
}
func objectEquals(a core.Object, b core.Object) error {
diff --git a/tag_test.go b/tag_test.go
index 5957678..811fee7 100644
--- a/tag_test.go
+++ b/tag_test.go
@@ -115,7 +115,7 @@ func (s *TagSuite) TestObject(c *C) {
func (s *TagSuite) TestTagItter(c *C) {
r := s.Repositories["https://github.com/git-fixtures/tags.git"]
- iter, err := r.s.ObjectStorage().Iter(core.TagObject)
+ iter, err := r.s.IterObjects(core.TagObject)
c.Assert(err, IsNil)
var count int
@@ -131,7 +131,7 @@ func (s *TagSuite) TestTagItter(c *C) {
func (s *TagSuite) TestTagIterError(c *C) {
r := s.Repositories["https://github.com/git-fixtures/tags.git"]
- iter, err := r.s.ObjectStorage().Iter(core.TagObject)
+ iter, err := r.s.IterObjects(core.TagObject)
c.Assert(err, IsNil)
i := NewTagIter(r, iter)
diff --git a/tree.go b/tree.go
index 9c97872..4d08396 100644
--- a/tree.go
+++ b/tree.go
@@ -51,7 +51,7 @@ func (t *Tree) File(path string) (*File, error) {
return nil, ErrFileNotFound
}
- obj, err := t.r.s.ObjectStorage().Get(core.BlobObject, e.Hash)
+ obj, err := t.r.s.Object(core.BlobObject, e.Hash)
if err != nil {
return nil, err
}
@@ -84,7 +84,7 @@ func (t *Tree) dir(baseName string) (*Tree, error) {
return nil, errDirNotFound
}
- obj, err := t.r.s.ObjectStorage().Get(core.TreeObject, entry.Hash)
+ obj, err := t.r.s.Object(core.TreeObject, entry.Hash)
if err != nil {
return nil, err
}
diff --git a/tree_test.go b/tree_test.go
index 86b4851..3220490 100644
--- a/tree_test.go
+++ b/tree_test.go
@@ -37,7 +37,7 @@ func (s *TreeSuite) TestDecode(c *C) {
func (s *TreeSuite) TestDecodeNonTree(c *C) {
hash := core.NewHash("9a48f23120e880dfbe41f7c9b7b708e9ee62a492")
- blob, err := s.Repository.s.ObjectStorage().Get(core.BlobObject, hash)
+ blob, err := s.Repository.s.Object(core.BlobObject, hash)
c.Assert(err, IsNil)
tree := &Tree{}
@@ -89,12 +89,12 @@ func (o *SortReadObject) SetType(t core.ObjectType) { o.t = t }
func (o *SortReadObject) Size() int64 { return o.sz }
func (o *SortReadObject) SetSize(s int64) { o.sz = s }
func (o *SortReadObject) Content() []byte { return o.cont }
-func (o *SortReadObject) Reader() (core.ObjectReader, error) {
+func (o *SortReadObject) Reader() (io.ReadCloser, error) {
return &SortReadCloser{pos: 0, data: o.cont}, nil
}
-func (o *SortReadObject) Writer() (core.ObjectWriter, error) { return o, nil }
-func (o *SortReadObject) Write(p []byte) (n int, err error) { return len(p), nil }
-func (o *SortReadObject) Close() error { return nil }
+func (o *SortReadObject) Writer() (io.WriteCloser, error) { return o, nil }
+func (o *SortReadObject) Write(p []byte) (n int, err error) { return len(p), nil }
+func (o *SortReadObject) Close() error { return nil }
// a ReadCloser that only returns 6 bytes at a time, to simulate incomplete reads.
type SortReadCloser struct {