-
Notifications
You must be signed in to change notification settings - Fork 0
/
storj.go
103 lines (89 loc) · 2.22 KB
/
storj.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
package storj
import (
"context"
"errors"
"io"
"net/url"
"strings"
"storj.io/common/socket"
"storj.io/uplink"
"github.com/jtolds/jam/backends"
"github.com/zeebo/errs"
)
var (
Error = errs.Class("storj error")
)
func init() {
backends.Register("storj", New)
}
type Backend struct {
p *uplink.Project
bucket string
prefix string
}
func New(ctx context.Context, u *url.URL) (backends.Backend, error) {
access, err := uplink.ParseAccess(u.Host)
if err != nil {
return nil, Error.Wrap(err)
}
p, err := (&uplink.Config{DialContext: socket.BackgroundDialer().DialContext}).OpenProject(ctx, access)
if err != nil {
return nil, Error.Wrap(err)
}
parts := strings.SplitN(strings.TrimPrefix(u.Path, "/"), "/", 2)
var prefix string
if len(parts) > 1 {
prefix = parts[1]
}
return &Backend{
p: p,
bucket: parts[0],
prefix: prefix,
}, nil
}
func (b *Backend) Get(ctx context.Context, path string, offset, length int64) (io.ReadCloser, error) {
path = b.prefix + path
d, err := b.p.DownloadObject(ctx, b.bucket, path, &uplink.DownloadOptions{Offset: offset, Length: length})
if errors.Is(err, uplink.ErrObjectNotFound) {
return d, Error.Wrap(backends.ErrNotExist)
}
return d, Error.Wrap(err)
}
func (b *Backend) Put(ctx context.Context, path string, data io.Reader) error {
path = b.prefix + path
u, err := b.p.UploadObject(ctx, b.bucket, path, nil)
if err != nil {
return Error.Wrap(err)
}
defer u.Abort()
_, err = io.Copy(u, data)
if err != nil {
return Error.Wrap(err)
}
return Error.Wrap(u.Commit())
}
func (b *Backend) Delete(ctx context.Context, path string) error {
path = b.prefix + path
_, err := b.p.DeleteObject(ctx, b.bucket, path)
if errors.Is(err, uplink.ErrObjectNotFound) {
return nil
}
return Error.Wrap(err)
}
func (b *Backend) List(ctx context.Context, prefix string, cb func(ctx context.Context, path string) error) error {
prefix = b.prefix + prefix
it := b.p.ListObjects(ctx, b.bucket, &uplink.ListObjectsOptions{
Prefix: prefix,
Recursive: true,
})
for it.Next() {
err := cb(ctx, strings.TrimPrefix(it.Item().Key, b.prefix))
if err != nil {
return err
}
}
return Error.Wrap(it.Err())
}
func (b *Backend) Close() error {
return Error.Wrap(b.p.Close())
}