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
}