diff options
author | Máximo Cuadros <mcuadros@gmail.com> | 2020-07-10 06:16:33 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-10 06:16:33 +0200 |
commit | 58ac8636795fa45f6dbb3dcd6f3c3ebb01da8627 (patch) | |
tree | e6115028814e950d7c9cbe86cd997c390c47b3ca | |
parent | ee580ee459d4eac1c434203cc264523acfae724a (diff) | |
parent | d0d47c3781674db571b18df0544f66d93decf342 (diff) | |
download | go-git-58ac8636795fa45f6dbb3dcd6f3c3ebb01da8627.tar.gz |
Merge pull request #121 from riking/cache-seek
plumbing: memoryobject, make blob reader seekable
-rw-r--r-- | plumbing/memory.go | 17 | ||||
-rw-r--r-- | plumbing/memory_test.go | 28 |
2 files changed, 42 insertions, 3 deletions
diff --git a/plumbing/memory.go b/plumbing/memory.go index b8e1e1b..21337cc 100644 --- a/plumbing/memory.go +++ b/plumbing/memory.go @@ -3,7 +3,6 @@ package plumbing import ( "bytes" "io" - "io/ioutil" ) // MemoryObject on memory Object implementation @@ -39,9 +38,11 @@ func (o *MemoryObject) Size() int64 { return o.sz } // afterwards func (o *MemoryObject) SetSize(s int64) { o.sz = s } -// Reader returns a ObjectReader used to read the object's content. +// Reader returns an io.ReadCloser used to read the object's content. +// +// For a MemoryObject, this reader is seekable. func (o *MemoryObject) Reader() (io.ReadCloser, error) { - return ioutil.NopCloser(bytes.NewBuffer(o.cont)), nil + return nopCloser{bytes.NewReader(o.cont)}, nil } // Writer returns a ObjectWriter used to write the object's content. @@ -59,3 +60,13 @@ func (o *MemoryObject) Write(p []byte) (n int, err error) { // Close releases any resources consumed by the object when it is acting as a // ObjectWriter. func (o *MemoryObject) Close() error { return nil } + +// nopCloser exposes the extra methods of bytes.Reader while nopping Close(). +// +// This allows clients to attempt seeking in a cached Blob's Reader. +type nopCloser struct { + *bytes.Reader +} + +// Close does nothing. +func (nc nopCloser) Close() error { return nil } diff --git a/plumbing/memory_test.go b/plumbing/memory_test.go index 879ed37..2a141f4 100644 --- a/plumbing/memory_test.go +++ b/plumbing/memory_test.go @@ -1,6 +1,7 @@ package plumbing import ( + "io" "io/ioutil" . "gopkg.in/check.v1" @@ -56,6 +57,33 @@ func (s *MemoryObjectSuite) TestReader(c *C) { c.Assert(b, DeepEquals, []byte("foo")) } +func (s *MemoryObjectSuite) TestSeekableReader(c *C) { + const pageSize = 4096 + const payload = "foo" + content := make([]byte, pageSize+len(payload)) + copy(content[pageSize:], []byte(payload)) + + o := &MemoryObject{cont: content} + + reader, err := o.Reader() + c.Assert(err, IsNil) + defer func() { c.Assert(reader.Close(), IsNil) }() + + rs, ok := reader.(io.ReadSeeker) + c.Assert(ok, Equals, true) + + _, err = rs.Seek(pageSize, io.SeekStart) + c.Assert(err, IsNil) + + b, err := ioutil.ReadAll(rs) + c.Assert(err, IsNil) + c.Assert(b, DeepEquals, []byte(payload)) + + // Check that our Reader isn't also accidentally writable + _, ok = reader.(io.WriteSeeker) + c.Assert(ok, Equals, false) +} + func (s *MemoryObjectSuite) TestWriter(c *C) { o := &MemoryObject{} |