summaryrefslogtreecommitdiff
path: root/packbuilder.go
diff options
context:
space:
mode:
authorCarlos Martín Nieto <[email protected]>2014-05-06 14:43:38 +0200
committerCarlos Martín Nieto <[email protected]>2014-05-06 14:43:38 +0200
commit7e3c361ac4c97f48d80d7ca63358e92ea464a087 (patch)
tree579c09cbba1f47254e7bfa685222e3e39ce62bbb /packbuilder.go
parent2594f3f889f93196bc9707ca6962f4f773806f10 (diff)
Packbuilder: use a callback for ForEach instead of a channel
Channels provide no means to report an error. Closing a channel could mean anything. This is particularly important when dealing with IO, which we do quite often in the pack builder. Use ForEach which returns an error instead.
Diffstat (limited to 'packbuilder.go')
-rw-r--r--packbuilder.go58
1 files changed, 27 insertions, 31 deletions
diff --git a/packbuilder.go b/packbuilder.go
index 70c4530..666f5c4 100644
--- a/packbuilder.go
+++ b/packbuilder.go
@@ -94,55 +94,51 @@ func (pb *Packbuilder) WriteToFile(name string, mode os.FileMode) error {
}
func (pb *Packbuilder) Write(w io.Writer) error {
- ch, stop := pb.ForEach()
- for slice := range ch {
+ return pb.ForEach(func(slice []byte) error {
_, err := w.Write(slice)
- if err != nil {
- close(stop)
- return err
- }
- }
- return nil
+ return err
+ })
}
func (pb *Packbuilder) Written() uint32 {
return uint32(C.git_packbuilder_written(pb.ptr))
}
+type PackbuilderForeachCallback func([]byte) error
type packbuilderCbData struct {
- ch chan<- []byte
- stop <-chan bool
+ callback PackbuilderForeachCallback
+ err error
}
//export packbuilderForEachCb
func packbuilderForEachCb(buf unsafe.Pointer, size C.size_t, payload unsafe.Pointer) int {
data := (*packbuilderCbData)(payload)
- ch := data.ch
- stop := data.stop
-
slice := C.GoBytes(buf, C.int(size))
- select {
- case <- stop:
- return -1
- case ch <- slice:
+
+ err := data.callback(slice)
+ if err != nil {
+ data.err = err
+ return C.GIT_EUSER
}
return 0
}
-func (pb *Packbuilder) forEachWrap(data *packbuilderCbData) {
- C._go_git_packbuilder_foreach(pb.ptr, unsafe.Pointer(data))
- close(data.ch)
-}
+// ForEach repeatedly calls the callback with new packfile data until
+// there is no more data or the callback returns an error
+func (pb *Packbuilder) ForEach(callback PackbuilderForeachCallback) error {
+ data := packbuilderCbData{
+ callback: callback,
+ err: nil,
+ }
-// 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
+ err := C._go_git_packbuilder_foreach(pb.ptr, unsafe.Pointer(&data))
+ if err == C.GIT_EUSER {
+ return data.err
+ }
+ if err < 0 {
+ return MakeGitError(err)
+ }
+
+ return nil
}