This repository has been archived by the owner on Dec 11, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 14
/
local_fs.go
142 lines (115 loc) · 3.22 KB
/
local_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
package storage
import (
"context"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
// DefaultLocalCreatePathMode is the default os.FileMode used when creating directories
// during a localFS.Create call.
const DefaultLocalCreatePathMode = os.FileMode(0o755)
// LocalCreatePathMode is the os.FileMode used when creating directories via localFS.Create
var LocalCreatePathMode = DefaultLocalCreatePathMode
// localFS is a local FS and Walker implementation.
type localFS string
func NewLocalFS(path string) FS {
fs := localFS(path)
return &fs
}
func (l *localFS) fullPath(path string) string {
return filepath.Join(string(*l), path)
}
func (l *localFS) wrapError(path string, err error) error {
if os.IsNotExist(err) {
return ¬ExistError{
Path: path,
}
}
return err
}
// Open implements FS.
func (l *localFS) Open(_ context.Context, path string, _ *ReaderOptions) (*File, error) {
path = l.fullPath(path)
f, err := os.Open(path)
if err != nil {
return nil, l.wrapError(path, err)
}
stat, err := f.Stat()
if err != nil {
return nil, l.wrapError(path, err)
}
return &File{
ReadCloser: f,
Attributes: Attributes{
ModTime: stat.ModTime(),
Size: stat.Size(),
},
}, nil
}
// Attributes implements FS.
func (l *localFS) Attributes(_ context.Context, path string, _ *ReaderOptions) (*Attributes, error) {
path = l.fullPath(path)
stat, err := os.Stat(path)
if err != nil {
return nil, l.wrapError(path, err)
}
return &Attributes{
ModTime: stat.ModTime(),
Size: stat.Size(),
}, nil
}
// Create implements FS. If the path contains any directories which do not already exist
// then Create will try to make them, returning an error if it fails.
func (l *localFS) Create(_ context.Context, path string, options *WriterOptions) (io.WriteCloser, error) {
path = l.fullPath(path)
dir := filepath.Dir(path)
if _, err := os.Stat(dir); os.IsNotExist(err) {
if err := os.MkdirAll(dir, LocalCreatePathMode); err != nil {
return nil, err
}
}
f, err := os.Create(path)
if err != nil {
return nil, err
}
if options != nil {
if !options.Attributes.CreationTime.IsZero() {
// There is no way to store the CreationTime, so overwrite the ModTime
// This is necessary so the CacheWrapper can use LocalFS
options.Attributes.ModTime = options.Attributes.CreationTime
}
if !options.Attributes.ModTime.IsZero() {
if err := os.Chtimes(path, options.Attributes.ModTime, options.Attributes.ModTime); err != nil {
return f, err
}
}
}
return f, nil
}
// Delete implements FS. All files underneath path will be removed.
func (l *localFS) Delete(_ context.Context, path string) error {
return os.RemoveAll(l.fullPath(path))
}
// Walk implements Walker.
func (l *localFS) Walk(_ context.Context, path string, fn WalkFn) error {
return filepath.Walk(l.fullPath(path), func(path string, f os.FileInfo, err error) error {
if err != nil {
return err
}
if !f.IsDir() {
path = strings.TrimPrefix(path, string(*l))
return fn(path)
}
return nil
})
}
func (l *localFS) URL(_ context.Context, path string, _ *SignedURLOptions) (string, error) {
path = l.fullPath(path)
_, err := os.Stat(path)
if err != nil {
return "", l.wrapError(path, err)
}
return fmt.Sprintf("file://%s", path), nil
}