forked from sourcegraph/checkup
-
Notifications
You must be signed in to change notification settings - Fork 0
/
fs.go
135 lines (112 loc) · 2.67 KB
/
fs.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
package checkup
import (
"encoding/json"
"io/ioutil"
"os"
"path/filepath"
"time"
)
const indexName = "index.json"
// FS is a way to store checkup results on the local filesystem.
type FS struct {
// The path to the directory where check files will be stored.
Dir string `json:"dir"`
// The URL corresponding to fs.Dir.
URL string `json:"url"`
// Check files older than CheckExpiry will be
// deleted on calls to Maintain(). If this is
// the zero value, no old check files will be
// deleted.
CheckExpiry time.Duration `json:"check_expiry,omitempty"`
}
// GetIndex returns the index from filesystem.
func (fs FS) GetIndex() (map[string]int64, error) {
return fs.readIndex()
}
func (fs FS) readIndex() (map[string]int64, error) {
index := map[string]int64{}
f, err := os.Open(filepath.Join(fs.Dir, indexName))
if os.IsNotExist(err) {
return index, nil
} else if err != nil {
return nil, err
}
defer f.Close()
err = json.NewDecoder(f).Decode(&index)
return index, err
}
func (fs FS) writeIndex(index map[string]int64) error {
f, err := os.Create(filepath.Join(fs.Dir, indexName))
if err != nil {
return err
}
defer f.Close()
return json.NewEncoder(f).Encode(index)
}
// Fetch fetches results from filesystem for the specified index.
func (fs FS) Fetch(name string) ([]Result, error) {
f, err := os.Open(filepath.Join(fs.Dir, name))
if err != nil {
return nil, err
}
var results []Result
err = json.NewDecoder(f).Decode(&results)
f.Close()
if err != nil {
return nil, err
}
return results, nil
}
// Store stores results on filesystem according to the configuration in fs.
func (fs FS) Store(results []Result) error {
// Write results to a new file
name := *GenerateFilename()
f, err := os.Create(filepath.Join(fs.Dir, name))
if err != nil {
return err
}
err = json.NewEncoder(f).Encode(results)
f.Close()
if err != nil {
return err
}
// Read current index file
index, err := fs.readIndex()
if err != nil {
return err
}
// Add new file to index
index[name] = time.Now().UnixNano()
// Write new index
return fs.writeIndex(index)
}
// Maintain deletes check files that are older than fs.CheckExpiry.
func (fs FS) Maintain() error {
if fs.CheckExpiry == 0 {
return nil
}
files, err := ioutil.ReadDir(fs.Dir)
if err != nil {
return err
}
index, err := fs.readIndex()
if err != nil {
return err
}
for _, f := range files {
if f.Name() == indexName {
continue
}
nsec, ok := index[f.Name()]
if !ok {
continue
}
if time.Since(time.Unix(0, nsec)) > fs.CheckExpiry {
if err := os.Remove(filepath.Join(fs.Dir, f.Name())); err != nil {
return err
}
delete(index, f.Name())
}
}
return fs.writeIndex(index)
}