/
release.go
143 lines (114 loc) · 2.94 KB
/
release.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
135
136
137
138
139
140
141
142
143
package main
import (
"io"
"io/ioutil"
"log"
"mime/multipart"
"os"
"path/filepath"
"regexp"
)
var (
reMetaDownloadURL = regexp.MustCompile(`"download_url":\s?"([^"]+?)"`)
reMd5 = regexp.MustCompile(`"md5_digest":\s?"([^"]+?)"`)
)
// Release represents a specific, versioned release of a package.
type Release struct {
Name string
Version string
DataDir string
Filename string
}
// Metadata reads and returns everything in the metadata file.
func (r Release) Metadata() (data []byte, err error) {
metaFile := r.MetadataFile()
if _, err := os.Stat(metaFile); os.IsNotExist(err) {
return data, err
}
return ioutil.ReadFile(metaFile)
}
// MetadataFile returns the path to the metadata file.
func (r Release) MetadataFile() string {
return filepath.Join(r.Directory(), "metadata.json")
}
// Path represents the actual file for a release.
func (r Release) Path() string {
return r.Name + "/" + r.Version + "/" + r.Filename
}
// DownloadURL fetches the location to download the package from.
func (r Release) DownloadURL() (url string) {
mdata, err := r.Metadata()
if err != nil {
// panic(err.Error())
return
}
matches := reMetaDownloadURL.FindSubmatch(mdata)
if len(matches) > 1 {
url = string(matches[1])
}
return
}
// Md5 returns the sum found from the original mirror.
func (r Release) Md5() (url string) {
mdata, err := r.Metadata()
if err != nil {
// panic(err.Error())
return
}
matches := reMd5.FindSubmatch(mdata)
if len(matches) > 1 {
url = string(matches[1])
}
return
}
// ReleaseFilePath points to the absolute location of a release.
func (r Release) ReleaseFilePath() string {
return filepath.Join(r.Directory(), r.Filename)
}
// Exists returns whether a release is present.
func (r Release) Exists() bool {
if r.Version == "" {
return false
}
if _, err := os.Stat(r.ReleaseFilePath()); err == nil || r.DownloadURL() != "" {
return true
}
return false
}
// StoreMetadata writes all metadata to a file.
func (r Release) StoreMetadata(data []byte) error {
return ioutil.WriteFile(r.MetadataFile(), data, 0644)
}
// StoreRelease saves what was uploaded. Buffered in case of large files.
func (r Release) StoreRelease(data multipart.File) {
f, err := os.Create(r.ReleaseFilePath())
if err != nil {
log.Println("Can't open file: " + r.ReleaseFilePath())
return
}
defer f.Close()
buf := make([]byte, 1024)
for {
n, err := data.Read(buf)
if err != nil && err != io.EOF {
log.Println("Couldn't write file: " + r.ReleaseFilePath())
break
}
if n == 0 {
break
}
if _, err := f.Write(buf[:n]); err != nil {
log.Println("Couldn't write file: " + r.ReleaseFilePath())
break
}
}
}
// Directory is the path to the release directory,
// creating it if it doesn't exist.
func (r Release) Directory() string {
projectDir := filepath.Join(r.DataDir, r.Name, r.Version)
if _, err := os.Stat(projectDir); os.IsNotExist(err) {
os.MkdirAll(projectDir, 0755)
}
return projectDir
}