@cryptotaxi247 / kubo / commits / f3c4f87ec

core/commands: Added GZIP compression to 'get'

Matt Bell committed Jan 22, 2015 at 12:30 UTC f3c4f87ec28d837888a4169b42058614037f8b82
1 file changed +63 -10
core/commands/get.go
+63 -10
@@ -3,6 +3,7 @@ package commands
3 import (
4 "archive/tar"
5 "bytes"
6 + "compress/gzip"
7 "fmt"
8 "io"
9 "os"
@@ -30,6 +31,9 @@ By default, the output will be stored at ./<ipfs-path>, but an alternate path
31 can be specified with '--output=<path>' or '-o=<path>'.
32
33 To output a TAR archive instead of unpacked files, use '--archive' or '-a'.
34 +
35 +To compress the output with GZIP compression, use '--compress' or '-C'. You
36 +may also specify the level of compression by specifying '-l=<1-9>'.
37 `,
38 },
39
@@ -39,6 +43,8 @@ To output a TAR archive instead of unpacked files, use '--archive' or '-a'.
43 Options: []cmds.Option{
44 cmds.StringOption("output", "o", "The path where output should be stored"),
45 cmds.BoolOption("archive", "a", "Output a TAR archive"),
46 + cmds.BoolOption("compress", "C", "Compress the output with GZIP compression"),
47 + cmds.IntOption("compression-level", "l", "The level of compression (an int between 1 and 9)"),
48 },
49 Run: func(req cmds.Request, res cmds.Response) {
50 node, err := req.Context().GetNode()
@@ -47,7 +53,17 @@ To output a TAR archive instead of unpacked files, use '--archive' or '-a'.
53 return
54 }
55
50 - reader, err := get(node, req.Arguments()[0])
56 + compress, _, _ := req.Option("compress").Bool()
57 + compressionLevel, found, _ := req.Option("compression-level").Int()
58 + if !found {
59 + if compress {
60 + compressionLevel = gzip.DefaultCompression
61 + } else {
62 + compressionLevel = gzip.NoCompression
63 + }
64 + }
65 +
66 + reader, err := get(node, req.Arguments()[0], compressionLevel)
67 if err != nil {
68 res.SetError(err, cmds.ErrNormal)
69 return
@@ -58,15 +74,22 @@ To output a TAR archive instead of unpacked files, use '--archive' or '-a'.
74 reader := res.Output().(io.Reader)
75 res.SetOutput(nil)
76
61 - outPath, _, _ := res.Request().Option("output").String()
77 + outPath, _, _ := req.Option("output").String()
78 if len(outPath) == 0 {
63 - outPath = res.Request().Arguments()[0]
79 + outPath = req.Arguments()[0]
80 }
81
66 - if archive, _, _ := res.Request().Option("archive").Bool(); archive {
82 + compress, _, _ := req.Option("compress").Bool()
83 + compressionLevel, found, _ := req.Option("compression-level").Int()
84 + compress = (compress && (compressionLevel > 0 || !found)) || compressionLevel > 0
85 +
86 + if archive, _, _ := req.Option("archive").Bool(); archive {
87 if !strings.HasSuffix(outPath, ".tar") {
88 outPath += ".tar"
89 }
90 + if compress {
91 + outPath += ".gz"
92 + }
93 fmt.Printf("Saving archive to %s\n", outPath)
94
95 file, err := os.Create(outPath)
@@ -98,7 +121,18 @@ To output a TAR archive instead of unpacked files, use '--archive' or '-a'.
121 pathIsDir = true
122 }
123
101 - tarReader := tar.NewReader(reader)
124 + var tarReader *tar.Reader
125 + if compress {
126 + gzipReader, err := gzip.NewReader(reader)
127 + if err != nil {
128 + res.SetError(err, cmds.ErrNormal)
129 + return
130 + }
131 + defer gzipReader.Close()
132 + tarReader = tar.NewReader(gzipReader)
133 + } else {
134 + tarReader = tar.NewReader(reader)
135 + }
136
137 for i := 0; ; i++ {
138 header, err := tarReader.Next()
@@ -167,11 +201,11 @@ To output a TAR archive instead of unpacked files, use '--archive' or '-a'.
201 },
202 }
203
170 -func get(node *core.IpfsNode, path string) (io.Reader, error) {
204 +func get(node *core.IpfsNode, path string, compression int) (io.Reader, error) {
205 buf := NewBufReadWriter()
206
207 go func() {
174 - err := copyFilesAsTar(node, buf, path)
208 + err := copyFilesAsTar(node, buf, path, compression)
209 if err != nil {
210 log.Error(err)
211 return
@@ -181,19 +215,38 @@ func get(node *core.IpfsNode, path string) (io.Reader, error) {
215 return buf, nil
216 }
217
184 -func copyFilesAsTar(node *core.IpfsNode, buf *bufReadWriter, path string) error {
185 - writer := tar.NewWriter(buf)
218 +func copyFilesAsTar(node *core.IpfsNode, buf *bufReadWriter, path string, compression int) error {
219 + var gzipWriter *gzip.Writer
220 + var writer *tar.Writer
221 + var err error
222 + if compression != gzip.NoCompression {
223 + gzipWriter, err = gzip.NewWriterLevel(buf, compression)
224 + if err != nil {
225 + return err
226 + }
227 + writer = tar.NewWriter(gzipWriter)
228 + } else {
229 + writer = tar.NewWriter(buf)
230 + }
231
187 - err := _copyFilesAsTar(node, writer, buf, path, nil)
232 + err = _copyFilesAsTar(node, writer, buf, path, nil)
233 if err != nil {
234 return err
235 }
236
237 + buf.mutex.Lock()
238 err = writer.Close()
239 if err != nil {
240 return err
241 }
242 + if gzipWriter != nil {
243 + err = gzipWriter.Close()
244 + if err != nil {
245 + return err
246 + }
247 + }
248 buf.Close()
249 + buf.mutex.Unlock()
250 buf.Signal()
251 return nil
252 }