forked from laher/someutils
/
zip.go
134 lines (126 loc) · 2.49 KB
/
zip.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package someutils
import (
"archive/zip"
"errors"
"github.com/laher/uggo"
"io"
"os"
"path/filepath"
)
type ArchiveItem struct {
//if FileSystemPath is empty, use Data instead
FileSystemPath string
ArchivePath string
Data []byte
}
func init() {
Register(Util{
"zip",
Zip})
}
func Zip(call []string) error {
flagSet := uggo.NewFlagSetDefault("zip", "[options] [files...]", VERSION)
err := flagSet.Parse(call[1:])
if err != nil {
flagSet.Usage()
return err
}
if flagSet.ProcessHelpOrVersion() {
return nil
}
args := flagSet.Args()
if len(args) < 2 {
flagSet.Usage()
return errors.New("Not enough args given")
}
err = ZipItems(args[0], args[1:])
if err != nil {
return err
}
return nil
}
func ZipItems(zipFilename string, itemsToArchive []string) error {
_, err := os.Stat(zipFilename)
var zf *os.File
if err != nil {
if os.IsNotExist(err) {
zf, err = os.Create(zipFilename)
if err != nil {
return err
}
} else {
return err
}
} else {
zf, err = os.Create(zipFilename)
if err != nil {
return err
}
}
defer zf.Close()
zw := zip.NewWriter(zf)
defer zw.Close()
//resources
for _, itemS := range itemsToArchive {
//todo: relative/full path checking
item := ArchiveItem{itemS, itemS, nil}
err = addFileToZIP(zw, item)
if err != nil {
return err
}
}
//get error where possible
err = zw.Close()
return err
}
func addFileToZIP(zw *zip.Writer, item ArchiveItem) error {
//fmt.Printf("Adding %s\n", item.FileSystemPath)
binfo, err := os.Stat(item.FileSystemPath)
if err != nil {
return err
}
if binfo.IsDir() {
header, err := zip.FileInfoHeader(binfo)
if err != nil {
return err
}
header.Method = zip.Deflate
header.Name = item.ArchivePath
_, err = zw.CreateHeader(header)
if err != nil {
return err
}
file, err := os.Open(item.FileSystemPath)
if err != nil {
return err
}
fis, err := file.Readdir(0)
for _, fi := range fis {
err = addFileToZIP(zw, ArchiveItem{filepath.Join(item.FileSystemPath, fi.Name()), filepath.Join(item.ArchivePath, fi.Name()), nil})
if err != nil {
return err
}
}
} else {
header, err := zip.FileInfoHeader(binfo)
if err != nil {
return err
}
header.Method = zip.Deflate
header.Name = item.ArchivePath
w, err := zw.CreateHeader(header)
if err != nil {
return err
}
bf, err := os.Open(item.FileSystemPath)
if err != nil {
return err
}
defer bf.Close()
_, err = io.Copy(w, bf)
if err != nil {
return err
}
}
return err
}