This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / spindle / storage / disk.go
2.0 kB 87 lines
1package storage 2 3import ( 4 "context" 5 "fmt" 6 "io" 7 "os" 8 "path/filepath" 9) 10 11type Disk struct { 12 root string 13} 14 15func NewDisk(root string) (*Disk, error) { 16 if root == "" { 17 return nil, fmt.Errorf("storage: disk backend requires a directory") 18 } 19 if err := os.MkdirAll(root, 0o755); err != nil { 20 return nil, fmt.Errorf("storage: create disk root: %w", err) 21 } 22 return &Disk{root: filepath.Clean(root)}, nil 23} 24 25func (d *Disk) path(key string) (string, error) { 26 if err := ValidateKey(key); err != nil { 27 return "", err 28 } 29 return filepath.Join(d.root, filepath.FromSlash(key)), nil 30} 31 32func (d *Disk) Get(_ context.Context, key string) (io.ReadCloser, error) { 33 p, err := d.path(key) 34 if err != nil { 35 return nil, err 36 } 37 f, err := os.Open(p) 38 if err != nil { 39 if os.IsNotExist(err) { 40 return nil, ErrNotExist 41 } 42 return nil, fmt.Errorf("storage: get %q: %w", key, err) 43 } 44 return f, nil 45} 46 47func (d *Disk) Put(_ context.Context, key string, r io.Reader) error { 48 p, err := d.path(key) 49 if err != nil { 50 return err 51 } 52 if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil { 53 return fmt.Errorf("storage: put %q: %w", key, err) 54 } 55 // dont let readers see a partial object 56 tmp, err := os.CreateTemp(filepath.Dir(p), ".tmp-*") 57 if err != nil { 58 return fmt.Errorf("storage: put %q: %w", key, err) 59 } 60 tmpName := tmp.Name() 61 defer os.Remove(tmpName) 62 if _, err := io.Copy(tmp, r); err != nil { 63 _ = tmp.Close() 64 return fmt.Errorf("storage: put %q: %w", key, err) 65 } 66 if err := tmp.Close(); err != nil { 67 return fmt.Errorf("storage: put %q: %w", key, err) 68 } 69 if err := os.Rename(tmpName, p); err != nil { 70 return fmt.Errorf("storage: put %q: %w", key, err) 71 } 72 return nil 73} 74 75func (d *Disk) Delete(_ context.Context, key string) error { 76 p, err := d.path(key) 77 if err != nil { 78 return err 79 } 80 if err := os.Remove(p); err != nil { 81 if os.IsNotExist(err) { 82 return nil 83 } 84 return fmt.Errorf("storage: delete %q: %w", key, err) 85 } 86 return nil 87}