From 20e952ce83e9a01ba70ced7cadad37541800e96d Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sat, 31 May 2014 16:08:02 +0900 Subject: [PATCH] types: add NewOnceCloser, use it in camget Change-Id: I465207031468a57f2840d5071fc27713d6184325 --- cmd/camget/camget.go | 6 ++++-- pkg/types/types.go | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/cmd/camget/camget.go b/cmd/camget/camget.go index aecea4d61..1786be197 100644 --- a/cmd/camget/camget.go +++ b/cmd/camget/camget.go @@ -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": diff --git a/pkg/types/types.go b/pkg/types/types.go index 4b1f4c8d8..aa08f7fa3 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -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{})