forked from goproxy/goproxy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cacher.go
144 lines (120 loc) · 3.02 KB
/
cacher.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
144
package goproxy
import (
"context"
"errors"
"hash"
"io"
"mime"
"os"
"path"
"strings"
"time"
)
// ErrCacheNotFound is the error resulting if a path search failed to find a
// cache.
var ErrCacheNotFound = errors.New("cache not found")
// Cacher is the interface that defines a set of methods used to cache module
// files for the `Goproxy`.
//
// If you are looking for some useful implementations of the `Cacher`, simply
// visit the "github.com/goproxy/goproxy/cacher" package.
type Cacher interface {
// NewHash returns a new instance of the `hash.Hash` used to compute the
// checksums of the caches.
NewHash() hash.Hash
// Cache returns the matched `Cache` for the name from the underlying
// cacher. It returns the `ErrCacheNotFound` if not found.
//
// It is the caller's responsibility to close the returned `Cache`.
Cache(ctx context.Context, name string) (Cache, error)
// SetCache sets the c to the underlying cacher.
//
// It is the caller's responsibility to close the c.
SetCache(ctx context.Context, c Cache) error
}
// Cache is the cache unit of the `Cacher`.
type Cache interface {
io.Reader
io.Seeker
io.Closer
// Name returns the unique Unix path style name.
Name() string
// MIMEType returns the MIME type.
MIMEType() string
// Size returns the length in bytes.
Size() int64
// ModTime returns the modification time.
ModTime() time.Time
// Checksum returns the checksum.
Checksum() []byte
}
// tempCache implements the `Cache`.
type tempCache struct {
io.Reader
io.Seeker
io.Closer
name string
mimeType string
size int64
modTime time.Time
checksum []byte
}
// newTempCache returns a new instance of the `tempCache` with the filename,
// name, and fileHash.
func newTempCache(filename, name string, fileHash hash.Hash) (Cache, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
var mimeType string
switch ext := strings.ToLower(path.Ext(name)); ext {
case ".info":
mimeType = "application/json; charset=utf-8"
case ".mod":
mimeType = "text/plain; charset=utf-8"
case ".zip":
mimeType = "application/zip"
default:
mimeType = mime.TypeByExtension(ext)
}
fileInfo, err := file.Stat()
if err != nil {
return nil, err
}
if _, err := io.Copy(fileHash, file); err != nil {
return nil, err
}
if _, err := file.Seek(0, io.SeekStart); err != nil {
return nil, err
}
return &tempCache{
Reader: file,
Seeker: file,
Closer: file,
name: name,
mimeType: mimeType,
size: fileInfo.Size(),
modTime: fileInfo.ModTime(),
checksum: fileHash.Sum(nil),
}, nil
}
// Name implements the `Cache`.
func (tc *tempCache) Name() string {
return tc.name
}
// MIMEType implements the `Cache`.
func (tc *tempCache) MIMEType() string {
return tc.mimeType
}
// Size implements the `Cache`.
func (tc *tempCache) Size() int64 {
return tc.size
}
// ModTime implements the `Cache`.
func (tc *tempCache) ModTime() time.Time {
return tc.modTime
}
// Checksum implements the `Cache`.
func (tc *tempCache) Checksum() []byte {
return tc.checksum
}