Merge pull request #38 from libgit2/odb-stream

Wrap the odb streams
This commit is contained in:
Vicent Martí 2013-09-17 08:03:34 -07:00
commit da5033fb98
2 changed files with 127 additions and 0 deletions

92
odb.go
View File

@ -72,6 +72,33 @@ func (v *Odb) ForEach() chan *Oid {
return ch return ch
} }
// NewReadStream opens a read stream from the ODB. Reading from it will give you the
// contents of the object.
func (v *Odb) NewReadStream(id *Oid) (*OdbReadStream, error) {
stream := new(OdbReadStream)
ret := C.git_odb_open_rstream(&stream.ptr, v.ptr, id.toC())
if ret < 0 {
return nil, LastError()
}
runtime.SetFinalizer(stream, (*OdbReadStream).Free)
return stream, nil
}
// NewWriteStream opens a write stream to the ODB, which allows you to
// create a new object in the database. The size and type must be
// known in advance
func (v *Odb) NewWriteStream(size int, otype ObjectType) (*OdbWriteStream, error) {
stream := new(OdbWriteStream)
ret := C.git_odb_open_wstream(&stream.ptr, v.ptr, C.size_t(size), C.git_otype(otype))
if ret < 0 {
return nil, LastError()
}
runtime.SetFinalizer(stream, (*OdbWriteStream).Free)
return stream, nil
}
type OdbObject struct { type OdbObject struct {
ptr *C.git_odb_object ptr *C.git_odb_object
} }
@ -102,3 +129,68 @@ func (object *OdbObject) Data() (data []byte) {
return blob return blob
} }
type OdbReadStream struct {
ptr *C.git_odb_stream
}
// Read reads from the stream
func (stream *OdbReadStream) Read(data []byte) (int, error) {
header := (*reflect.SliceHeader)(unsafe.Pointer(&data))
ptr := (*C.char)(unsafe.Pointer(header.Data))
size := C.size_t(header.Cap)
ret := C.git_odb_stream_read(stream.ptr, ptr, size)
if ret < 0 {
return 0, LastError()
}
header.Len = int(ret)
return len(data), nil
}
// Close is a dummy function in order to implement the Closer and
// ReadCloser interfaces
func (stream *OdbReadStream) Close() error {
return nil
}
func (stream *OdbReadStream) Free() {
runtime.SetFinalizer(stream, nil)
C.git_odb_stream_free(stream.ptr)
}
type OdbWriteStream struct {
ptr *C.git_odb_stream
Id Oid
}
// Write writes to the stream
func (stream *OdbWriteStream) Write(data []byte) (int, error) {
header := (*reflect.SliceHeader)(unsafe.Pointer(&data))
ptr := (*C.char)(unsafe.Pointer(header.Data))
size := C.size_t(header.Len)
ret := C.git_odb_stream_write(stream.ptr, ptr, size)
if ret < 0 {
return 0, LastError()
}
return len(data), nil
}
// Close signals that all the data has been written and stores the
// resulting object id in the stream's Id field.
func (stream *OdbWriteStream) Close() error {
ret := C.git_odb_stream_finalize_write(stream.Id.toC(), stream.ptr)
if ret < 0 {
return LastError()
}
return nil
}
func (stream *OdbWriteStream) Free() {
runtime.SetFinalizer(stream, nil)
C.git_odb_stream_free(stream.ptr)
}

35
odb_test.go Normal file
View File

@ -0,0 +1,35 @@
package git
import (
"io"
"os"
"testing"
)
func TestOdbStream(t *testing.T) {
repo := createTestRepo(t)
defer os.RemoveAll(repo.Workdir())
_, _ = seedTestRepo(t, repo)
odb, error := repo.Odb()
checkFatal(t, error)
str := "hello, world!"
stream, error := odb.NewWriteStream(len(str), OBJ_BLOB)
checkFatal(t, error)
n, error := io.WriteString(stream, str)
checkFatal(t, error)
if n != len(str) {
t.Fatalf("Bad write length %v != %v", n, len(str))
}
error = stream.Close()
checkFatal(t, error)
expectedId, error := NewOidFromString("30f51a3fba5274d53522d0f19748456974647b4f")
checkFatal(t, error)
if stream.Id.Cmp(expectedId) != 0 {
t.Fatal("Wrong data written")
}
}