-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfs.go
150 lines (114 loc) · 2.29 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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package fss
import (
"fmt"
"io"
"io/fs"
"os"
"sort"
"strings"
"time"
)
type FS struct {
fss map[string]fs.FS
}
func New() FS {
return FS{fss: map[string]fs.FS{}}
}
func (fss FS) Add(name string, f fs.FS) {
fss.fss[name] = f
}
func (fss FS) Open(name string) (fs.File, error) {
if name == "" {
return nil, fmt.Errorf("could not find path")
}
if name == "." {
return rootFile{fss: &fss}, nil
}
v, p := separate(name)
tfs, ok := fss.fss[v]
if !ok {
return nil, fmt.Errorf("could not find %s in fss", v)
}
return tfs.Open(p)
}
func (fss FS) ReadDir(name string) ([]fs.DirEntry, error) {
ret := []fs.DirEntry{}
if !fs.ValidPath(name) {
return nil, os.ErrInvalid
}
if name == "." {
for key, val := range fss.fss {
ret = append(ret, dirEntry{name: key, fs: val})
}
sort.Slice(ret, func(i, j int) bool { return ret[i].Name() < ret[j].Name() })
return ret, nil
}
v, p := separate(name)
tfs, ok := fss.fss[v]
if !ok {
return ret, os.ErrNotExist
}
return fs.ReadDir(tfs, p)
}
type dirEntry struct {
name string
fs fs.FS
}
func (d dirEntry) Info() (fs.FileInfo, error) {
f, err := d.fs.Open(".")
if err != nil {
return nil, err
}
return f.Stat()
}
func (d dirEntry) IsDir() bool {
return true
}
func (d dirEntry) Name() string {
return d.name
}
func (dirEntry) Type() fs.FileMode {
return fs.ModeDir
}
type rootFile struct {
fss *FS
}
func (rootFile) Close() error {
return nil
}
func (rootFile) Read([]byte) (int, error) {
return 0, io.EOF
}
func (rootFile) Stat() (fs.FileInfo, error) {
return rootFileInfo{}, nil
}
func (r rootFile) ReadDir(n int) ([]fs.DirEntry, error) {
return r.fss.ReadDir(".")
}
type rootFileInfo struct {
}
func (rootFileInfo) IsDir() bool {
return true
}
func (rootFileInfo) ModTime() time.Time {
return time.Now()
}
func (rootFileInfo) Mode() fs.FileMode {
return fs.ModeDir
}
func (rootFileInfo) Name() string {
return "fss"
}
func (rootFileInfo) Size() int64 {
return 0
}
func (rootFileInfo) Sys() any {
return nil
}
func separate(name string) (string, string) {
sp := strings.SplitN(name, "/", 2)
if len(sp) == 1 {
return sp[0], "."
}
return sp[0], sp[1]
}