package storage import ( "bytes" "io/ioutil" "os" "path" "time" "github.com/ncw/rclone/fs" "github.com/ncw/rclone/fs/config" "github.com/ncw/rclone/fs/object" _ "github.com/ncw/rclone/backend/crypt" _ "github.com/ncw/rclone/backend/drive" _ "github.com/ncw/rclone/backend/local" _ "github.com/ncw/rclone/backend/s3" ) type RClone struct { ns string } func NewRClone(rclone string, ns ...string) (*RClone, error) { namespace := path.Join(ns...) _, err := os.Stat(rclone) if err == nil { os.Setenv("RCLONE_CONFIG", rclone) config.ConfigPath = rclone config.LoadConfig() } return &RClone{ ns: namespace, }, err } func (rc *RClone) Get(key string, ns ...string) ([]byte, error) { namespace := rc.ns if len(ns) > 0 { namespace = path.Join(rc.ns, resolveNamespace(ns)) } key = path.Join(namespace, key) f, err := fs.NewFs(path.Dir(key)) if err != nil { return nil, err } obj, err := f.NewObject(path.Base(key)) if err != nil { return nil, err } r, err := obj.Open() if err != nil { return nil, err } return ioutil.ReadAll(r) } func (rc *RClone) Set(key string, value []byte, ns ...string) error { if len(value) == 0 { return rc.Del(key, ns...) } namespace := rc.ns if len(ns) > 0 { namespace = path.Join(rc.ns, resolveNamespace(ns)) } key = path.Join(namespace, key) f, err := fs.NewFs(path.Dir(key)) if err != nil { return err } obj := object.NewStaticObjectInfo(path.Base(key), time.Now(), 0, true, nil, f) _, err = f.Put(bytes.NewReader(value), obj) return err } func (rc *RClone) Del(key string, ns ...string) error { namespace := rc.ns if len(ns) > 0 { namespace = path.Join(rc.ns, resolveNamespace(ns)) } key = path.Join(namespace, key) f, err := fs.NewFs(path.Dir(key)) if err != nil { return err } obj, err := f.NewObject(path.Base(key)) if err == fs.ErrorObjectNotFound { return nil } if err != nil { return nil } return obj.Remove() } func (rc *RClone) Close() error { return nil } func (rc *RClone) List(ns []string, limits ...string) ([]string, error) { namespace := rc.ns if len(ns) > 0 { namespace = path.Join(rc.ns, resolveNamespace(ns)) } limits = resolveLimits(limits) f, err := fs.NewFs(namespace) if err != nil { return nil, err } entries, err := f.List("") if err != nil { return nil, err } names := make([]string, 0) for _, entry := range entries { name := entry.Remote() if rc.inRange(name, limits[0], limits[1]) { names = append(names, name) } } return names, nil } func (rc *RClone) inRange(k, start, stop string) bool { return k != "" && k >= start && k <= stop }