@cryptotaxi247 / kubo / commits / 379817870

Don't use tar reader for '-C' only flag

Currently `ipfs get -C <hash>` returns error even if <hash> is a file. This PR is for the case when the compress flag is enabled, use the dagreader directly and pipe to a gzip processor. License: MIT Signed-off-by: rht <rhtbot@gmail.com>

rht committed Jun 11, 2015 at 20:44 UTC 37981787054fadf87615557f892dbd28a139ca79
1 file changed +50 -18
core/commands/get.go
+50 -18
@@ -1,6 +1,7 @@
1 package commands
2
3 import (
4 + "bufio"
5 "compress/gzip"
6 "errors"
7 "fmt"
@@ -16,6 +17,7 @@ import (
17 core "github.com/ipfs/go-ipfs/core"
18 path "github.com/ipfs/go-ipfs/path"
19 tar "github.com/ipfs/go-ipfs/thirdparty/tar"
20 + uio "github.com/ipfs/go-ipfs/unixfs/io"
21 utar "github.com/ipfs/go-ipfs/unixfs/tar"
22 )
23
@@ -63,7 +65,20 @@ may also specify the level of compression by specifying '-l=<1-9>'.
65 return
66 }
67
66 - reader, err := get(req.Context().Context, node, req.Arguments()[0], cmplvl)
68 + // Validate path string
69 + p, err := path.ParsePath(req.Arguments()[0])
70 + if err != nil {
71 + res.SetError(fmt.Errorf("failed to validate path: %v", err), cmds.ErrNormal)
72 + return
73 + }
74 + var reader io.Reader
75 +
76 + if archive, _, _ := req.Option("archive").Bool(); !archive && cmplvl != gzip.NoCompression {
77 + // only use this when the flag is '-C' without '-a'
78 + reader, err = getZip(req.Context().Context, node, p, cmplvl)
79 + } else {
80 + reader, err = get(req.Context().Context, node, p, cmplvl)
81 + }
82 if err != nil {
83 res.SetError(err, cmds.ErrNormal)
84 return
@@ -89,8 +104,8 @@ may also specify the level of compression by specifying '-l=<1-9>'.
104 return
105 }
106
92 - if archive, _, _ := req.Option("archive").Bool(); archive {
93 - if !strings.HasSuffix(outPath, ".tar") {
107 + if archive, _, _ := req.Option("archive").Bool(); archive || cmplvl != gzip.NoCompression {
108 + if archive && !strings.HasSuffix(outPath, ".tar") {
109 outPath += ".tar"
110 }
111 if cmplvl != gzip.NoCompression {
@@ -127,19 +142,7 @@ may also specify the level of compression by specifying '-l=<1-9>'.
142 bar.Output = os.Stderr
143
144 // wrap the reader with the progress bar proxy reader
130 - // if the output is compressed, also wrap it in a gzip.Reader
131 - var reader io.Reader
132 - if cmplvl != gzip.NoCompression {
133 - gzipReader, err := gzip.NewReader(outReader)
134 - if err != nil {
135 - res.SetError(err, cmds.ErrNormal)
136 - return
137 - }
138 - defer gzipReader.Close()
139 - reader = bar.NewProxyReader(gzipReader)
140 - } else {
141 - reader = bar.NewProxyReader(outReader)
142 - }
145 + reader := bar.NewProxyReader(outReader)
146
147 bar.Start()
148 defer bar.Finish()
@@ -166,8 +169,7 @@ func getCompressOptions(req cmds.Request) (int, error) {
169 return gzip.NoCompression, nil
170 }
171
169 -func get(ctx context.Context, node *core.IpfsNode, p string, compression int) (io.Reader, error) {
170 - pathToResolve := path.Path(p)
172 +func get(ctx context.Context, node *core.IpfsNode, pathToResolve path.Path, compression int) (io.Reader, error) {
173 dagnode, err := core.Resolve(ctx, node, pathToResolve)
174 if err != nil {
175 return nil, err
@@ -175,3 +177,33 @@ func get(ctx context.Context, node *core.IpfsNode, p string, compression int) (i
177
178 return utar.NewReader(pathToResolve, node.DAG, dagnode, compression)
179 }
180 +
181 +// getZip is equivalent to `ipfs getdag $hash | gzip`
182 +func getZip(ctx context.Context, node *core.IpfsNode, pathToResolve path.Path, compression int) (io.Reader, error) {
183 + dagnode, err := core.Resolve(ctx, node, pathToResolve)
184 + if err != nil {
185 + return nil, err
186 + }
187 +
188 + reader, err := uio.NewDagReader(ctx, dagnode, node.DAG)
189 + if err != nil {
190 + return nil, err
191 + }
192 +
193 + pr, pw := io.Pipe()
194 + gw, err := gzip.NewWriterLevel(pw, compression)
195 + if err != nil {
196 + return nil, err
197 + }
198 + bufin := bufio.NewReader(reader)
199 + go func() {
200 + _, err := bufin.WriteTo(gw)
201 + if err != nil {
202 + log.Error("Fail to compress the stream")
203 + }
204 + gw.Close()
205 + pw.Close()
206 + }()
207 +
208 + return pr, nil
209 +}