github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/unixfs/archive/archive.go (about) 1 package archive 2 3 import ( 4 "bufio" 5 "compress/gzip" 6 "io" 7 "path" 8 9 cxt "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" 10 11 mdag "github.com/ipfs/go-ipfs/merkledag" 12 tar "github.com/ipfs/go-ipfs/unixfs/archive/tar" 13 uio "github.com/ipfs/go-ipfs/unixfs/io" 14 ) 15 16 // DefaultBufSize is the buffer size for gets. for now, 1MB, which is ~4 blocks. 17 // TODO: does this need to be configurable? 18 var DefaultBufSize = 1048576 19 20 // DagArchive is equivalent to `ipfs getdag $hash | maybe_tar | maybe_gzip` 21 func DagArchive(ctx cxt.Context, nd *mdag.Node, name string, dag mdag.DAGService, archive bool, compression int) (io.Reader, error) { 22 23 _, filename := path.Split(name) 24 25 // need to connect a writer to a reader 26 piper, pipew := io.Pipe() 27 28 // use a buffered writer to parallelize task 29 bufw := bufio.NewWriterSize(pipew, DefaultBufSize) 30 31 // compression determines whether to use gzip compression. 32 var maybeGzw io.Writer 33 if compression != gzip.NoCompression { 34 var err error 35 maybeGzw, err = gzip.NewWriterLevel(bufw, compression) 36 if err != nil { 37 return nil, err 38 } 39 } else { 40 maybeGzw = bufw 41 } 42 43 if !archive && compression != gzip.NoCompression { 44 // the case when the node is a file 45 dagr, err := uio.NewDagReader(ctx, nd, dag) 46 if err != nil { 47 pipew.CloseWithError(err) 48 return nil, err 49 } 50 51 go func() { 52 if _, err := dagr.WriteTo(maybeGzw); err != nil { 53 pipew.CloseWithError(err) 54 return 55 } 56 pipew.Close() // everything seems to be ok. 57 }() 58 } else { 59 // the case for 1. archive, and 2. not archived and not compressed, in which tar is used anyway as a transport format 60 61 // construct the tar writer 62 w, err := tar.NewWriter(ctx, dag, archive, compression, maybeGzw) 63 if err != nil { 64 return nil, err 65 } 66 67 go func() { 68 // write all the nodes recursively 69 if err := w.WriteNode(nd, filename); err != nil { 70 pipew.CloseWithError(err) 71 return 72 } 73 if err := bufw.Flush(); err != nil { 74 pipew.CloseWithError(err) 75 return 76 } 77 w.Close() 78 pipew.Close() // everything seems to be ok. 79 }() 80 } 81 82 return piper, nil 83 }