diff options
Diffstat (limited to 'packbuilder.go')
| -rw-r--r-- | packbuilder.go | 65 |
1 files changed, 51 insertions, 14 deletions
diff --git a/packbuilder.go b/packbuilder.go index 8cc03bd..333f183 100644 --- a/packbuilder.go +++ b/packbuilder.go @@ -1,7 +1,6 @@ package git /* -#cgo pkg-config: libgit2 #include <git2.h> #include <git2/errors.h> #include <git2/pack.h> @@ -11,9 +10,10 @@ extern int _go_git_packbuilder_foreach(git_packbuilder *pb, void *payload); */ import "C" import ( + "io" + "os" "runtime" "unsafe" - "io" ) type Packbuilder struct { @@ -22,6 +22,10 @@ type Packbuilder struct { func (repo *Repository) NewPackbuilder() (*Packbuilder, error) { builder := &Packbuilder{} + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + ret := C.git_packbuilder_new(&builder.ptr, repo.ptr) if ret != 0 { return nil, LastError() @@ -38,6 +42,10 @@ func (pb *Packbuilder) Free() { func (pb *Packbuilder) Insert(id *Oid, name string) error { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + ret := C.git_packbuilder_insert(pb.ptr, id.toC(), cname) if ret != 0 { return LastError() @@ -46,6 +54,9 @@ func (pb *Packbuilder) Insert(id *Oid, name string) error { } func (pb *Packbuilder) InsertCommit(id *Oid) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + ret := C.git_packbuilder_insert_commit(pb.ptr, id.toC()) if ret != 0 { return LastError() @@ -54,6 +65,9 @@ func (pb *Packbuilder) InsertCommit(id *Oid) error { } func (pb *Packbuilder) InsertTree(id *Oid) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + ret := C.git_packbuilder_insert_tree(pb.ptr, id.toC()) if ret != 0 { return LastError() @@ -65,10 +79,14 @@ func (pb *Packbuilder) ObjectCount() uint32 { return uint32(C.git_packbuilder_object_count(pb.ptr)) } -func (pb *Packbuilder) WriteToFile(name string) error { +func (pb *Packbuilder) WriteToFile(name string, mode os.FileMode) error { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) - ret := C.git_packbuilder_write(pb.ptr, cname) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_packbuilder_write(pb.ptr, cname, C.uint(mode.Perm()), nil, nil) if ret != 0 { return LastError() } @@ -76,10 +94,11 @@ func (pb *Packbuilder) WriteToFile(name string) error { } func (pb *Packbuilder) Write(w io.Writer) error { - ch := pb.ForEach() + ch, stop := pb.ForEach() for slice := range ch { _, err := w.Write(slice) if err != nil { + close(stop) return err } } @@ -90,22 +109,40 @@ func (pb *Packbuilder) Written() uint32 { return uint32(C.git_packbuilder_written(pb.ptr)) } +type packbuilderCbData struct { + ch chan<- []byte + stop <-chan bool +} + //export packbuilderForEachCb func packbuilderForEachCb(buf unsafe.Pointer, size C.size_t, payload unsafe.Pointer) int { - ch := *(*chan []byte)(payload) + data := (*packbuilderCbData)(payload) + ch := data.ch + stop := data.stop slice := C.GoBytes(buf, C.int(size)) - ch <- slice + select { + case <- stop: + return -1 + case ch <- slice: + } + return 0 } -func (pb *Packbuilder) forEachWrap(ch chan []byte) { - C._go_git_packbuilder_foreach(pb.ptr, unsafe.Pointer(&ch)) - close(ch) +func (pb *Packbuilder) forEachWrap(data *packbuilderCbData) { + C._go_git_packbuilder_foreach(pb.ptr, unsafe.Pointer(data)) + close(data.ch) } -func (pb *Packbuilder) ForEach() chan []byte { - ch := make(chan []byte, 0) - go pb.forEachWrap(ch) - return ch +// Foreach sends the packfile as slices through the "data" channel. If +// you want to stop the pack-building process (e.g. there's an error +// writing to the output), close or write a value into the "stop" +// channel. +func (pb *Packbuilder) ForEach() (<-chan []byte, chan<- bool) { + ch := make(chan []byte) + stop := make(chan bool) + data := packbuilderCbData{ch, stop} + go pb.forEachWrap(&data) + return ch, stop } |
