diff options
Diffstat (limited to 'storage/filesystem')
-rw-r--r-- | storage/filesystem/internal/index/index.go | 24 | ||||
-rw-r--r-- | storage/filesystem/object.go | 54 | ||||
-rw-r--r-- | storage/filesystem/object_test.go | 17 |
3 files changed, 88 insertions, 7 deletions
diff --git a/storage/filesystem/internal/index/index.go b/storage/filesystem/internal/index/index.go index 737aca6..233dcbd 100644 --- a/storage/filesystem/internal/index/index.go +++ b/storage/filesystem/internal/index/index.go @@ -35,18 +35,26 @@ func NewFromIdx(r io.Reader) (Index, error) { // NewFrompackfile returns a new index from a packfile reader. func NewFromPackfile(rs io.ReadSeeker) (Index, error) { - index := make(Index) + s := packfile.NewSeekable(rs) + return newFromPackfile(rs, s) +} - r := packfile.NewSeekable(rs) - p := packfile.NewParser(r) +func NewFromPackfileInMemory(rs io.Reader) (Index, error) { + s := packfile.NewStream(rs) + return newFromPackfile(rs, s) +} +func newFromPackfile(r io.Reader, s packfile.ReadRecaller) (Index, error) { + index := make(Index) + + p := packfile.NewParser(s) count, err := p.ReadHeader() if err != nil { return nil, err } for i := 0; i < int(count); i++ { - offset, err := r.Offset() + offset, err := s.Offset() if err != nil { return nil, err } @@ -56,17 +64,19 @@ func NewFromPackfile(rs io.ReadSeeker) (Index, error) { return nil, err } - err = r.Remember(offset, obj) + err = s.Remember(offset, obj) if err != nil { return nil, err } - err = index.Set(obj.Hash(), offset) - if err != nil { + if err = index.Set(obj.Hash(), offset); err != nil { return nil, err } } + //The trailer records 20-byte SHA-1 checksum of all of the above. + p.ReadHash() + return index, nil } diff --git a/storage/filesystem/object.go b/storage/filesystem/object.go index 0696c70..fbcc9ae 100644 --- a/storage/filesystem/object.go +++ b/storage/filesystem/object.go @@ -1,7 +1,9 @@ package filesystem import ( + "bytes" "fmt" + "io" "os" "gopkg.in/src-d/go-git.v4/core" @@ -30,6 +32,58 @@ func (s *ObjectStorage) NewObject() core.Object { return &core.MemoryObject{} } +// Writer method not supported on Memory storage +func (o *ObjectStorage) Writer() (io.WriteCloser, error) { + file := bytes.NewBuffer(nil) + return newPackWrite(o, file), nil +} + +type packWriter struct { + writer io.Writer + pipeReader io.ReadCloser + pipeWriter io.WriteCloser + file io.Writer + result chan error +} + +func newPackWrite(o *ObjectStorage, file io.Writer) io.WriteCloser { + r, w := io.Pipe() + + ch := make(chan error) + go func(r io.ReadCloser) { + defer r.Close() + index, err := index.NewFromPackfileInMemory(r) + o.index = index + + ch <- err + }(r) + + return &packWriter{ + writer: io.MultiWriter(w, file), + pipeReader: r, + pipeWriter: w, + file: file, + result: ch, + } + +} + +func (w *packWriter) Write(p []byte) (int, error) { + return w.writer.Write(p) +} + +func (w *packWriter) Close() error { + defer func() { + close(w.result) + }() + + if err := w.pipeWriter.Close(); err != nil { + return err + } + + return <-w.result +} + // Set adds a new object to the storage. As this functionality is not // yet supported, this method always returns a "not implemented yet" // error an zero hash. diff --git a/storage/filesystem/object_test.go b/storage/filesystem/object_test.go index 5752f79..78ec20c 100644 --- a/storage/filesystem/object_test.go +++ b/storage/filesystem/object_test.go @@ -2,6 +2,7 @@ package filesystem import ( "fmt" + "io" "io/ioutil" "os" "reflect" @@ -62,6 +63,22 @@ func (s *FsSuite) TearDownSuite(c *C) { } } +func (s *FsSuite) TestWriter(c *C) { + r, err := os.Open("../../formats/packfile/fixtures/git-fixture.ofs-delta") + c.Assert(err, IsNil) + + o := &ObjectStorage{} + w, err := o.Writer() + c.Assert(err, IsNil) + + n, err := io.Copy(w, r) + c.Assert(err, IsNil) + c.Check(n, Equals, int64(85300)) + + c.Assert(o.index, HasLen, 28) + c.Assert(w.Close(), IsNil) +} + func (s *FsSuite) TestHashNotFound(c *C) { sto := s.newObjectStorage(c, "binary-relations") types := []core.ObjectType{core.AnyObject, core.TagObject, core.CommitObject, core.BlobObject, core.TreeObject} |