forked from gyepisam/redux
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprerequisite.go
159 lines (125 loc) · 3.57 KB
/
prerequisite.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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Copyright 2014 Gyepi Sam. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package redux
// Prerequisite from a source to a target.
type Prerequisite struct {
Path string // path back to target of prerequisite.
*Metadata // target's metadata upon record creation.
}
// PutPrerequisite stores the given prerequisite using a key based on the event and hash.
func (f *File) PutPrerequisite(event Event, hash Hash, prereq Prerequisite) error {
return f.Put(f.makeKey(REQUIRES, event, hash), prereq)
}
// GetPrerequisite returns the prerequisite for the event and hash.
// If the record does not exist, found is false and err is nil.
func (f *File) GetPrerequisite(event Event, hash Hash) (prereq Prerequisite, found bool, err error) {
found, err = f.Get(f.makeKey(REQUIRES, event, hash), &prereq)
return
}
type record struct {
key string
*Prerequisite
}
func prefixed(f *File, prefix string) ([]*record, error) {
rows, err := f.db.GetRecords(prefix)
if err != nil {
return nil, err
}
out := make([]*record, len(rows))
for i, row := range rows {
if decoded, err := decodePrerequisite(row.Value); err != nil {
return nil, err
} else {
out[i] = &record{row.Key, &decoded}
}
}
return out, nil
}
func (f *File) eventRecords(events ...Event) ([]*record, error) {
if len(events) == 0 {
return prefixed(f, f.makeKey(REQUIRES))
}
var records []*record
for _, event := range events {
eventRecords, err := prefixed(f, f.makeKey(REQUIRES, event))
if err != nil {
return nil, err
}
records = append(records, eventRecords...)
}
return records, nil
}
// Prerequisites returns a slice of prerequisites for the file.
func (f *File) Prerequisites(events ...Event) (out []*Prerequisite, err error) {
records, err := f.eventRecords(events...)
if err != nil {
return
}
out = make([]*Prerequisite, len(records))
for i, rec := range records {
out[i] = rec.Prerequisite
}
return
}
// PrerequisiteFiles returns a slice of *File objects for the file's prerequisites for the list of events.
func (f *File) PrerequisiteFiles(events ...Event) ([]*File, error) {
records, err := f.eventRecords(events...)
if err != nil {
return nil, err
}
out := make([]*File, len(records))
for i, rec := range records {
if file, err := rec.File(f.RootDir); err != nil {
return nil, err
} else {
out[i] = file
}
}
return out, nil
}
// DeletePrerequisite removes a single prerequisite.
func (f *File) DeletePrerequisite(event Event, hash Hash) error {
return f.Delete(f.makeKey(REQUIRES, event, hash))
}
type visitor func(*record) error
func visit(f *File, prefix string, fn visitor) error {
records, err := prefixed(f, prefix)
if err != nil {
return err
}
for _, rec := range records {
if err := fn(rec); err != nil {
return err
}
}
return nil
}
func destroy(f *File, prefix string) error {
return visit(f, prefix, func(rec *record) error {
return f.Delete(rec.key)
})
}
// DeleteAutoPrerequisites removes all of the file's system generated prerequisites.
func (f *File) DeleteAutoPrerequisites() error {
return destroy(f, f.makeKey(REQUIRES, AUTO))
}
// DeleteAllPrerequisites removed all of the file's prerequisites.
func (f *File) DeleteAllPrerequisites() error {
return destroy(f, f.makeKey(REQUIRES))
}
func (p *Prerequisite) IsCurrent(rootDir string) (isCurrent bool, err error) {
f, err := p.File(rootDir)
if err != nil {
return
}
m, err := f.NewMetadata()
if err != nil {
return
}
isCurrent = p.Equal(m)
if !isCurrent {
return
}
return f.IsCurrent()
}