-
Notifications
You must be signed in to change notification settings - Fork 3
/
zipfiles.go
104 lines (77 loc) · 1.69 KB
/
zipfiles.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
package main
import (
"archive/zip"
"flag"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/zemnmez/monorepo/go/flag/flagutil"
)
var output flagutil.FileFlag
const help = `zipfiles -output [target] [files...]
Zipfiles takes a set of files and produces a zip file
that is based in the longest common denominator
of the paths of those files.
For example:
zipfiles -output out.zip /home/thomas/files/cool.png \
/home/thomas/files/cool2.png /home/thomas/files/extra/cool3.png
Will produce a zip file containing cool.png, cool2.png and
extra/cool3.png
`
func init() {
flag.Var(&output, "output", "target zip file (or '-' for stdout)")
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), help)
flag.PrintDefaults()
}
}
func hasCommonPrefix(prefix string, s ...string) bool {
for _, v := range s {
if !strings.HasPrefix(v, prefix) {
return false
}
}
return true
}
func commonPrefix(s ...string) string {
var i int
for ; ; i++ {
if i > len(s[0]) || !hasCommonPrefix(s[0][:i], s[1:]...) {
return s[0][:i]
}
}
}
func main() {
defer output.Close()
flag.Parse()
if err := Do(); err != nil {
panic(err)
}
}
func Do() (err error) {
var filePaths = flag.CommandLine.Args()
for i, path := range filePaths {
filePaths[i] = filepath.Clean(path)
}
z := zip.NewWriter(output)
defer z.Close()
prefix := commonPrefix(filePaths...)
for _, filepath := range filePaths {
var file = flagutil.FileFlag{
Flags: os.O_RDONLY,
}
file.Set(filepath)
defer file.Close()
dst, err := z.Create(strings.TrimPrefix(filepath, prefix))
if err != nil {
return err
}
_, err = io.Copy(dst, file)
if err != nil {
return err
}
}
return nil
}