]>
Commit | Line | Data |
---|---|---|
bae9f6d2 JC |
1 | package getter |
2 | ||
3 | import ( | |
4 | "archive/zip" | |
5 | "fmt" | |
6 | "io" | |
7 | "os" | |
8 | "path/filepath" | |
9 | ) | |
10 | ||
11 | // ZipDecompressor is an implementation of Decompressor that can | |
12 | // decompress tar.gzip files. | |
13 | type ZipDecompressor struct{} | |
14 | ||
15 | func (d *ZipDecompressor) Decompress(dst, src string, dir bool) error { | |
16 | // If we're going into a directory we should make that first | |
17 | mkdir := dst | |
18 | if !dir { | |
19 | mkdir = filepath.Dir(dst) | |
20 | } | |
21 | if err := os.MkdirAll(mkdir, 0755); err != nil { | |
22 | return err | |
23 | } | |
24 | ||
25 | // Open the zip | |
26 | zipR, err := zip.OpenReader(src) | |
27 | if err != nil { | |
28 | return err | |
29 | } | |
30 | defer zipR.Close() | |
31 | ||
32 | // Check the zip integrity | |
33 | if len(zipR.File) == 0 { | |
34 | // Empty archive | |
35 | return fmt.Errorf("empty archive: %s", src) | |
36 | } | |
37 | if !dir && len(zipR.File) > 1 { | |
38 | return fmt.Errorf("expected a single file: %s", src) | |
39 | } | |
40 | ||
41 | // Go through and unarchive | |
42 | for _, f := range zipR.File { | |
43 | path := dst | |
44 | if dir { | |
45 | path = filepath.Join(path, f.Name) | |
46 | } | |
47 | ||
48 | if f.FileInfo().IsDir() { | |
49 | if !dir { | |
50 | return fmt.Errorf("expected a single file: %s", src) | |
51 | } | |
52 | ||
53 | // A directory, just make the directory and continue unarchiving... | |
54 | if err := os.MkdirAll(path, 0755); err != nil { | |
55 | return err | |
56 | } | |
57 | ||
58 | continue | |
59 | } | |
60 | ||
61 | // Create the enclosing directories if we must. ZIP files aren't | |
62 | // required to contain entries for just the directories so this | |
63 | // can happen. | |
64 | if dir { | |
65 | if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { | |
66 | return err | |
67 | } | |
68 | } | |
69 | ||
70 | // Open the file for reading | |
71 | srcF, err := f.Open() | |
72 | if err != nil { | |
73 | return err | |
74 | } | |
75 | ||
76 | // Open the file for writing | |
77 | dstF, err := os.Create(path) | |
78 | if err != nil { | |
79 | srcF.Close() | |
80 | return err | |
81 | } | |
82 | _, err = io.Copy(dstF, srcF) | |
83 | srcF.Close() | |
84 | dstF.Close() | |
85 | if err != nil { | |
86 | return err | |
87 | } | |
88 | ||
89 | // Chmod the file | |
90 | if err := os.Chmod(path, f.Mode()); err != nil { | |
91 | return err | |
92 | } | |
93 | } | |
94 | ||
95 | return nil | |
96 | } |