diff options
Diffstat (limited to 'vendor/github.com/hashicorp/go-getter/decompress_tgz.go')
-rw-r--r-- | vendor/github.com/hashicorp/go-getter/decompress_tgz.go | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/go-getter/decompress_tgz.go b/vendor/github.com/hashicorp/go-getter/decompress_tgz.go new file mode 100644 index 0000000..e8b1c31 --- /dev/null +++ b/vendor/github.com/hashicorp/go-getter/decompress_tgz.go | |||
@@ -0,0 +1,99 @@ | |||
1 | package getter | ||
2 | |||
3 | import ( | ||
4 | "archive/tar" | ||
5 | "compress/gzip" | ||
6 | "fmt" | ||
7 | "io" | ||
8 | "os" | ||
9 | "path/filepath" | ||
10 | ) | ||
11 | |||
12 | // TarGzipDecompressor is an implementation of Decompressor that can | ||
13 | // decompress tar.gzip files. | ||
14 | type TarGzipDecompressor struct{} | ||
15 | |||
16 | func (d *TarGzipDecompressor) Decompress(dst, src string, dir bool) error { | ||
17 | // If we're going into a directory we should make that first | ||
18 | mkdir := dst | ||
19 | if !dir { | ||
20 | mkdir = filepath.Dir(dst) | ||
21 | } | ||
22 | if err := os.MkdirAll(mkdir, 0755); err != nil { | ||
23 | return err | ||
24 | } | ||
25 | |||
26 | // File first | ||
27 | f, err := os.Open(src) | ||
28 | if err != nil { | ||
29 | return err | ||
30 | } | ||
31 | defer f.Close() | ||
32 | |||
33 | // Gzip compression is second | ||
34 | gzipR, err := gzip.NewReader(f) | ||
35 | if err != nil { | ||
36 | return fmt.Errorf("Error opening a gzip reader for %s: %s", src, err) | ||
37 | } | ||
38 | defer gzipR.Close() | ||
39 | |||
40 | // Once gzip decompressed we have a tar format | ||
41 | tarR := tar.NewReader(gzipR) | ||
42 | done := false | ||
43 | for { | ||
44 | hdr, err := tarR.Next() | ||
45 | if err == io.EOF { | ||
46 | if !done { | ||
47 | // Empty archive | ||
48 | return fmt.Errorf("empty archive: %s", src) | ||
49 | } | ||
50 | |||
51 | return nil | ||
52 | } | ||
53 | if err != nil { | ||
54 | return err | ||
55 | } | ||
56 | |||
57 | path := dst | ||
58 | if dir { | ||
59 | path = filepath.Join(path, hdr.Name) | ||
60 | } | ||
61 | |||
62 | if hdr.FileInfo().IsDir() { | ||
63 | if !dir { | ||
64 | return fmt.Errorf("expected a single file: %s", src) | ||
65 | } | ||
66 | |||
67 | // A directory, just make the directory and continue unarchiving... | ||
68 | if err := os.MkdirAll(path, 0755); err != nil { | ||
69 | return err | ||
70 | } | ||
71 | |||
72 | continue | ||
73 | } | ||
74 | |||
75 | // We have a file. If we already decoded, then it is an error | ||
76 | if !dir && done { | ||
77 | return fmt.Errorf("expected a single file, got multiple: %s", src) | ||
78 | } | ||
79 | |||
80 | // Mark that we're done so future in single file mode errors | ||
81 | done = true | ||
82 | |||
83 | // Open the file for writing | ||
84 | dstF, err := os.Create(path) | ||
85 | if err != nil { | ||
86 | return err | ||
87 | } | ||
88 | _, err = io.Copy(dstF, tarR) | ||
89 | dstF.Close() | ||
90 | if err != nil { | ||
91 | return err | ||
92 | } | ||
93 | |||
94 | // Chmod the file | ||
95 | if err := os.Chmod(path, hdr.FileInfo().Mode()); err != nil { | ||
96 | return err | ||
97 | } | ||
98 | } | ||
99 | } | ||