forked from gobuffalo/genny
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathdisk.go
111 lines (96 loc) · 2.07 KB
/
disk.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
package genny
import (
"bytes"
"io"
"os"
"runtime"
"sort"
"strings"
"sync"
"github.com/gobuffalo/packd"
)
// Disk is a virtual file system that works
// with both dry and wet runners. Perfect for seeding
// Files or non-destructively deleting files
type Disk struct {
Runner *Runner
files map[string]File
moot *sync.RWMutex
}
func (d *Disk) AddBox(box packd.Walker) error {
return box.Walk(func(path string, file packd.File) error {
d.Add(NewFile(path, file))
return nil
})
}
// Files returns a sorted list of all the files in the disk
func (d *Disk) Files() []File {
var files []File
for _, f := range d.files {
if s, ok := f.(io.Seeker); ok {
s.Seek(0, 0)
}
files = append(files, f)
}
sort.Slice(files, func(i, j int) bool {
return files[i].Name() < files[j].Name()
})
return files
}
func newDisk(r *Runner) *Disk {
return &Disk{
Runner: r,
files: map[string]File{},
moot: &sync.RWMutex{},
}
}
// Remove a file(s) from the virtual disk.
func (d *Disk) Remove(name string) {
d.moot.Lock()
defer d.moot.Unlock()
for f, _ := range d.files {
if strings.HasPrefix(f, name) {
delete(d.files, f)
}
}
}
// Delete calls the Runner#Delete function
func (d *Disk) Delete(name string) error {
return d.Runner.Delete(name)
}
// Add file to the virtual disk
func (d *Disk) Add(f File) {
d.moot.Lock()
defer d.moot.Unlock()
d.files[f.Name()] = f
}
// Find a file from the virtual disk. If the file doesn't
// exist it will try to read the file from the physical disk.
func (d *Disk) Find(name string) (File, error) {
d.moot.RLock()
if f, ok := d.files[name]; ok {
if seek, ok := f.(io.Seeker); ok {
seek.Seek(0, 0)
}
d.moot.RUnlock()
return f, nil
}
d.moot.RUnlock()
gf := NewFile(name, bytes.NewReader([]byte("")))
osname := name
if runtime.GOOS == "windows" {
osname = strings.Replace(osname, "/", "\\", -1)
}
f, err := os.Open(osname)
if err != nil {
return gf, err
}
defer f.Close()
bb := &bytes.Buffer{}
if _, err := io.Copy(bb, f); err != nil {
return gf, err
}
gf = NewFile(name, bb)
d.Add(gf)
return gf, nil
}