forked from gomods/athens
-
Notifications
You must be signed in to change notification settings - Fork 0
/
module.go
96 lines (77 loc) · 2.27 KB
/
module.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
package module
import (
"archive/zip"
"fmt"
"io"
"os"
"path/filepath"
"strings"
ignore "github.com/sabhiram/go-gitignore"
"github.com/spf13/afero"
)
const (
gitIgnoreFilename = ".gitignore"
)
// MakeZip takes dir and module info and generates vgo valid zip
// the dir must end with a "/"
func MakeZip(fs afero.Fs, dir, module, version string) *io.PipeReader {
ignoreParser := getIgnoreParser(fs, dir)
pr, pw := io.Pipe()
go func() {
zw := zip.NewWriter(pw)
defer zw.Close()
walkFn := walkFunc(fs, zw, dir, module, version, ignoreParser)
err := afero.Walk(fs, dir, walkFn)
pw.CloseWithError(err)
}()
return pr
}
func walkFunc(fs afero.Fs, zw *zip.Writer, dir, module, version string, ignoreParser ignore.IgnoreParser) filepath.WalkFunc {
return func(path string, info os.FileInfo, err error) error {
if err != nil || info == nil || info.IsDir() {
return err
}
fileName := getFileName(path, dir, module, version)
if ignoreParser.MatchesPath(fileName) {
return nil
}
fileContent, err := afero.ReadFile(fs, path)
if err != nil {
return err
}
f, err := zw.Create(fileName)
if err != nil {
return err
}
_, err = f.Write(fileContent)
return err
}
}
func getIgnoreParser(fs afero.Fs, dir string) ignore.IgnoreParser {
gitFilePath := filepath.Join(dir, gitIgnoreFilename)
gitParser := compileIgnoreFileAndLines(fs, gitFilePath, gitIgnoreFilename)
dsStoreParser := dsStoreIgnoreParser{}
return newMultiIgnoreParser(gitParser, dsStoreParser)
}
func compileIgnoreFileAndLines(fs afero.Fs, fpath string, lines ...string) ignore.IgnoreParser {
buffer, err := afero.ReadFile(fs, fpath)
if err != nil {
return nil
}
s := strings.Split(string(buffer), "\n")
ip, err := ignore.CompileIgnoreLines(append(s, lines...)...)
if err != nil {
// if we return ip, then it won't be a nil interface,
// even if ip is a nil pointer.
return nil
}
return ip
}
// getFileName composes filename for zip to match standard specified as
// module@version/{filename}
func getFileName(path, dir, module, version string) string {
filename := strings.TrimPrefix(path, dir)
filename = strings.TrimLeftFunc(filename, func(r rune) bool { return r == os.PathSeparator })
moduleID := fmt.Sprintf("%s@%s", module, version)
return filepath.Join(moduleID, filename)
}