-
Notifications
You must be signed in to change notification settings - Fork 9
/
file_handler.go
84 lines (71 loc) · 1.75 KB
/
file_handler.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
package fprintf
import (
"context"
"fmt"
"io"
"os"
"path"
"strings"
)
var (
fileHandlers map[string]FileHandler = make(map[string]FileHandler)
)
// FileHandler returns an io.WriteCloser that will handle the details of writing to the given
// filename. The filename could respresent a resource, such as a database, or a file.
type FileHandler func(ctx context.Context, filename string) (io.WriteCloser, error)
func init() {
fileHandlers["file"] = newFileHandler
}
type fileHandler struct {
name string
tempTemp string
f io.WriteCloser
}
func newFileHandler(ctx context.Context, filename string) (io.WriteCloser, error) {
dirname := path.Dir(filename)
isTemp := false
if strings.HasPrefix(filename, "/$tmp/") {
dirname = ""
filename = strings.TrimPrefix(filename, "/$tmp/")
isTemp = true
}
baseFile := path.Base(filename)
f, err := os.CreateTemp(dirname, baseFile)
if err != nil {
return nil, err
}
if isTemp {
filename = path.Join(os.TempDir(), baseFile)
}
fh := &fileHandler{
name: filename,
f: f,
tempTemp: f.Name(),
}
go fh.watchTilClose(ctx)
return fh, nil
}
func (fh *fileHandler) watchTilClose(ctx context.Context) {
<-ctx.Done()
fh.f.Close()
os.Remove(fh.tempTemp)
}
func (fh *fileHandler) Write(p []byte) (n int, err error) {
return fh.f.Write(p)
}
func (fh *fileHandler) Close() error {
if err := fh.f.Close(); err != nil {
return err
}
if err := os.Rename(fh.tempTemp, fh.name); err != nil {
return err
}
return nil
}
// RegisterFileHandler a new file handler. This will panic if the name is already registered.
func RegisterFileHandler(name string, f FileHandler) {
if _, ok := fileHandlers[name]; ok {
panic(fmt.Sprintf("fprintf: %s already registered", name))
}
fileHandlers[name] = f
}