types: add NewOnceCloser, use it in camget

Change-Id: I465207031468a57f2840d5071fc27713d6184325
This commit is contained in:
Brad Fitzpatrick 2014-05-31 16:08:02 +09:00
parent 6914346584
commit 20e952ce83
2 changed files with 27 additions and 2 deletions

View File

@ -35,6 +35,7 @@ import (
"camlistore.org/pkg/index"
"camlistore.org/pkg/osutil"
"camlistore.org/pkg/schema"
"camlistore.org/pkg/types"
)
var (
@ -172,7 +173,8 @@ func smartFetch(src blob.Fetcher, targ string, br blob.Ref) error {
if err != nil {
return err
}
defer rc.Close()
rcc := types.NewOnceCloser(rc)
defer rcc.Close()
sniffer := index.NewBlobSniffer(br)
_, err = io.CopyN(sniffer, rc, sniffSize)
@ -199,7 +201,7 @@ func smartFetch(src blob.Fetcher, targ string, br blob.Ref) error {
_, err = io.Copy(f, r)
return err
}
rc.Close()
rcc.Close()
switch b.Type() {
case "directory":

View File

@ -28,6 +28,7 @@ import (
"regexp"
"runtime"
"strings"
"sync"
"time"
)
@ -213,6 +214,28 @@ func U32(n int64) uint32 {
return uint32(n)
}
// NewOnceCloser returns a Closer wrapping c which only calls Close on c
// once. Subsequent calls to Close return nil.
func NewOnceCloser(c io.Closer) io.Closer {
return &onceCloser{c: c}
}
type onceCloser struct {
mu sync.Mutex
c io.Closer
}
func (c *onceCloser) Close() error {
c.mu.Lock()
defer c.mu.Unlock()
if c.c == nil {
return nil
}
err := c.c.Close()
c.c = nil
return err
}
// TB is a copy of Go 1.2's testing.TB.
type TB interface {
Error(args ...interface{})