aboutsummaryrefslogtreecommitdiffstats
path: root/storage
diff options
context:
space:
mode:
authorMáximo Cuadros <mcuadros@gmail.com>2016-02-17 00:24:31 +0100
committerMáximo Cuadros <mcuadros@gmail.com>2016-02-17 11:46:00 +0100
commita964e32d92c53a47ce7c46d589a18c62133b8c50 (patch)
tree4c094cd6afb95cb2832f866b9411276418435819 /storage
parent1ac00554c3b5f88d2ddc2e28e7cfcdcad9d9f4bb (diff)
downloadgo-git-a964e32d92c53a47ce7c46d589a18c62133b8c50.tar.gz
storages: memory object
Diffstat (limited to 'storage')
-rw-r--r--storage/memory/object.go55
-rw-r--r--storage/memory/object_test.go67
-rw-r--r--storage/memory/storage.go83
-rw-r--r--storage/memory/storage_test.go51
4 files changed, 256 insertions, 0 deletions
diff --git a/storage/memory/object.go b/storage/memory/object.go
new file mode 100644
index 0000000..7fee252
--- /dev/null
+++ b/storage/memory/object.go
@@ -0,0 +1,55 @@
+package memory
+
+import (
+ "bytes"
+ "io"
+
+ "gopkg.in/src-d/go-git.v2/core"
+)
+
+// Object on memory core.Object implementation
+type Object struct {
+ t core.ObjectType
+ h core.Hash
+ content []byte
+ size int64
+}
+
+// Hash return the object Hash, the hash is calculated on-the-fly the first
+// time is called, the subsequent calls the same Hash is returned even in the
+// type or the content has changed. The Hash is only generated if the size of
+// the content is exactly the Object.Size
+func (o *Object) Hash() core.Hash {
+ if o.h == core.ZeroHash && int64(len(o.content)) == o.size {
+ o.h = core.ComputeHash(o.t, o.content)
+ }
+
+ return o.h
+}
+
+// Type return the core.ObjectType
+func (o *Object) Type() core.ObjectType { return o.t }
+
+// SetType sets the core.ObjectType
+func (o *Object) SetType(t core.ObjectType) { o.t = t }
+
+// Size return the size of the object
+func (o *Object) Size() int64 { return o.size }
+
+// SetSize set the object size, the given size should be written afterwards
+func (o *Object) SetSize(s int64) { o.size = s }
+
+// Reader returns a io.Reader used to read the object content
+func (o *Object) Reader() io.Reader {
+ return bytes.NewBuffer(o.content)
+}
+
+// Writer returns a io.Writed used to write the object content
+func (o *Object) Writer() io.Writer {
+ return o
+}
+
+func (o *Object) Write(p []byte) (n int, err error) {
+ o.content = append(o.content, p...)
+ return len(p), nil
+}
diff --git a/storage/memory/object_test.go b/storage/memory/object_test.go
new file mode 100644
index 0000000..b606eb2
--- /dev/null
+++ b/storage/memory/object_test.go
@@ -0,0 +1,67 @@
+package memory
+
+import (
+ "io/ioutil"
+ "testing"
+
+ . "gopkg.in/check.v1"
+ "gopkg.in/src-d/go-git.v2/core"
+)
+
+func Test(t *testing.T) { TestingT(t) }
+
+type ObjectSuite struct{}
+
+var _ = Suite(&ObjectSuite{})
+
+func (s *ObjectSuite) TestHash(c *C) {
+ o := &Object{}
+ o.SetType(core.BlobObject)
+ o.SetSize(14)
+
+ _, err := o.Write([]byte("Hello, World!\n"))
+ c.Assert(err, IsNil)
+
+ c.Assert(o.Hash().String(), Equals, "8ab686eafeb1f44702738c8b0f24f2567c36da6d")
+
+ o.SetType(core.CommitObject)
+ c.Assert(o.Hash().String(), Equals, "8ab686eafeb1f44702738c8b0f24f2567c36da6d")
+}
+
+func (s *ObjectSuite) TestHashNotFilled(c *C) {
+ o := &Object{}
+ o.SetType(core.BlobObject)
+ o.SetSize(14)
+
+ c.Assert(o.Hash(), Equals, core.ZeroHash)
+}
+
+func (s *ObjectSuite) TestType(c *C) {
+ o := &Object{}
+ o.SetType(core.BlobObject)
+ c.Assert(o.Type(), Equals, core.BlobObject)
+}
+
+func (s *ObjectSuite) TestSize(c *C) {
+ o := &Object{}
+ o.SetSize(42)
+ c.Assert(o.Size(), Equals, int64(42))
+}
+
+func (s *ObjectSuite) TestReader(c *C) {
+ o := &Object{content: []byte("foo")}
+
+ b, err := ioutil.ReadAll(o.Reader())
+ c.Assert(err, IsNil)
+ c.Assert(b, DeepEquals, []byte("foo"))
+}
+
+func (s *ObjectSuite) TestWriter(c *C) {
+ o := &Object{}
+
+ n, err := o.Writer().Write([]byte("foo"))
+ c.Assert(err, IsNil)
+ c.Assert(n, Equals, 3)
+
+ c.Assert(o.content, DeepEquals, []byte("foo"))
+}
diff --git a/storage/memory/storage.go b/storage/memory/storage.go
new file mode 100644
index 0000000..4c106cc
--- /dev/null
+++ b/storage/memory/storage.go
@@ -0,0 +1,83 @@
+package memory
+
+import (
+ "fmt"
+
+ "gopkg.in/src-d/go-git.v2/core"
+)
+
+var ErrUnsupportedObjectType = fmt.Errorf("unsupported object type")
+
+// 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
+ Trees map[core.Hash]core.Object
+ Blobs map[core.Hash]core.Object
+}
+
+// NewObjectStorage returns a new empty ObjectStorage
+func NewObjectStorage() *ObjectStorage {
+ return &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),
+ }
+}
+
+// New returns a new empty memory.Object
+func (o *ObjectStorage) New() (core.Object, error) {
+ return &Object{}, nil
+}
+
+// Set stores an object, the object should be properly filled before set it.
+func (o *ObjectStorage) Set(obj core.Object) (core.Hash, error) {
+ h := obj.Hash()
+ o.Objects[h] = obj
+
+ switch obj.Type() {
+ case core.CommitObject:
+ o.Commits[h] = o.Objects[h]
+ case core.TreeObject:
+ o.Trees[h] = o.Objects[h]
+ case core.BlobObject:
+ o.Blobs[h] = o.Objects[h]
+ default:
+ return h, ErrUnsupportedObjectType
+ }
+
+ return h, nil
+}
+
+// Get returns a object with the given hash
+func (o *ObjectStorage) Get(h core.Hash) (core.Object, error) {
+ obj, ok := o.Objects[h]
+ if !ok {
+ return nil, core.ObjectNotFoundErr
+ }
+
+ return obj, nil
+}
+
+// Iter returns a core.ObjectIter for the given core.ObjectTybe
+func (o *ObjectStorage) Iter(t core.ObjectType) core.ObjectIter {
+ var series []core.Object
+ switch t {
+ case core.CommitObject:
+ series = flattenObjectMap(o.Commits)
+ case core.TreeObject:
+ series = flattenObjectMap(o.Trees)
+ case core.BlobObject:
+ series = flattenObjectMap(o.Blobs)
+ }
+ return core.NewObjectSliceIter(series)
+}
+
+func flattenObjectMap(m map[core.Hash]core.Object) []core.Object {
+ objects := make([]core.Object, 0, len(m))
+ for _, obj := range m {
+ objects = append(objects, obj)
+ }
+ return objects
+}
diff --git a/storage/memory/storage_test.go b/storage/memory/storage_test.go
new file mode 100644
index 0000000..4059dfa
--- /dev/null
+++ b/storage/memory/storage_test.go
@@ -0,0 +1,51 @@
+package memory
+
+import (
+ . "gopkg.in/check.v1"
+ "gopkg.in/src-d/go-git.v2/core"
+)
+
+type ObjectStorageSuite struct{}
+
+var _ = Suite(&ObjectStorageSuite{})
+
+func (s *ObjectStorageSuite) TestNew(c *C) {
+ os := NewObjectStorage()
+
+ o, err := os.New()
+ c.Assert(err, IsNil)
+ c.Assert(o.Size(), Equals, int64(0))
+}
+
+func (s *ObjectStorageSuite) TestSet(c *C) {
+ os := NewObjectStorage()
+
+ o, err := os.New()
+ c.Assert(err, IsNil)
+
+ o.SetType(core.CommitObject)
+ o.SetSize(3)
+ o.Writer().Write([]byte("foo"))
+
+ h, err := os.Set(o)
+ c.Assert(h.String(), Equals, "bc9968d75e48de59f0870ffb71f5e160bbbdcf52")
+}
+
+func (s *ObjectStorageSuite) TestGet(c *C) {
+ os := NewObjectStorage()
+
+ o, err := os.New()
+ c.Assert(err, IsNil)
+
+ o.SetType(core.CommitObject)
+ o.SetSize(3)
+ o.Writer().Write([]byte("foo"))
+
+ h, err := os.Set(o)
+ c.Assert(err, IsNil)
+
+ ro, err := os.Get(h)
+ c.Assert(err, IsNil)
+
+ c.Assert(ro, DeepEquals, o)
+}