From 301756ba03cd287342383df906d7db42bc135c63 Mon Sep 17 00:00:00 2001 From: Andy Hsu Date: Mon, 13 Mar 2023 15:35:37 +0800 Subject: [PATCH] feat(drivers): alias a new storage with multi path (close #3248) --- drivers/alias/driver.go | 106 +++++++++++++++++++++++++++++++++++++ drivers/alias/meta.go | 27 ++++++++++ drivers/alias/types.go | 1 + drivers/alias/util.go | 81 ++++++++++++++++++++++++++++ drivers/all.go | 1 + drivers/template/driver.go | 16 +++--- drivers/template/meta.go | 19 ++++--- 7 files changed, 235 insertions(+), 16 deletions(-) create mode 100644 drivers/alias/driver.go create mode 100644 drivers/alias/meta.go create mode 100644 drivers/alias/types.go create mode 100644 drivers/alias/util.go diff --git a/drivers/alias/driver.go b/drivers/alias/driver.go new file mode 100644 index 00000000000..a1308dc4cdf --- /dev/null +++ b/drivers/alias/driver.go @@ -0,0 +1,106 @@ +package alias + +import ( + "context" + "errors" + "strings" + + "github.com/alist-org/alist/v3/internal/driver" + "github.com/alist-org/alist/v3/internal/errs" + "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/pkg/utils" +) + +type Alias struct { + model.Storage + Addition + pathMap map[string][]string +} + +func (d *Alias) Config() driver.Config { + return config +} + +func (d *Alias) GetAddition() driver.Additional { + return &d.Addition +} + +func (d *Alias) Init(ctx context.Context) error { + if d.Paths == "" { + return errors.New("paths is required") + } + d.pathMap = make(map[string][]string) + for _, path := range strings.Split(d.Paths, "\n") { + path = strings.TrimSpace(path) + if path == "" { + continue + } + k, v := getPair(path) + d.pathMap[k] = append(d.pathMap[k], v) + } + return nil +} + +func (d *Alias) Drop(ctx context.Context) error { + d.pathMap = nil + return nil +} + +func (d *Alias) Get(ctx context.Context, path string) (model.Obj, error) { + if utils.PathEqual(path, "/") { + return &model.Object{ + Name: "Root", + IsFolder: true, + Path: "/", + }, nil + } + root, sub := getRootAndPath(path) + dsts, ok := d.pathMap[root] + if !ok { + return nil, errs.ObjectNotFound + } + for _, dst := range dsts { + obj, err := d.get(ctx, path, dst, sub) + if err == nil { + return obj, nil + } + } + return nil, errs.ObjectNotFound +} + +func (d *Alias) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) { + path := dir.GetPath() + if utils.PathEqual(path, "/") { + return d.listRoot(), nil + } + root, sub := getRootAndPath(path) + dsts, ok := d.pathMap[root] + if !ok { + return nil, errs.ObjectNotFound + } + var objs []model.Obj + for _, dst := range dsts { + tmp, err := d.list(ctx, dst, sub) + if err == nil { + objs = append(objs, tmp...) + } + } + return objs, nil +} + +func (d *Alias) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) { + root, sub := getRootAndPath(file.GetPath()) + dsts, ok := d.pathMap[root] + if !ok { + return nil, errs.ObjectNotFound + } + for _, dst := range dsts { + link, err := d.link(ctx, dst, sub, args) + if err == nil { + return link, nil + } + } + return nil, errs.ObjectNotFound +} + +var _ driver.Driver = (*Alias)(nil) diff --git a/drivers/alias/meta.go b/drivers/alias/meta.go new file mode 100644 index 00000000000..6611e1dc302 --- /dev/null +++ b/drivers/alias/meta.go @@ -0,0 +1,27 @@ +package alias + +import ( + "github.com/alist-org/alist/v3/internal/driver" + "github.com/alist-org/alist/v3/internal/op" +) + +type Addition struct { + // Usually one of two + // driver.RootPath + // define other + Paths string `json:"paths" required:"true" type:"text"` +} + +var config = driver.Config{ + Name: "Alias", + LocalSort: true, + NoCache: true, + NoUpload: true, + DefaultRoot: "/", +} + +func init() { + op.RegisterDriver(func() driver.Driver { + return &Alias{} + }) +} diff --git a/drivers/alias/types.go b/drivers/alias/types.go new file mode 100644 index 00000000000..e560393da66 --- /dev/null +++ b/drivers/alias/types.go @@ -0,0 +1 @@ +package alias diff --git a/drivers/alias/util.go b/drivers/alias/util.go new file mode 100644 index 00000000000..69a88330d81 --- /dev/null +++ b/drivers/alias/util.go @@ -0,0 +1,81 @@ +package alias + +import ( + "context" + stdpath "path" + "strings" + + "github.com/alist-org/alist/v3/internal/fs" + "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/pkg/utils" +) + +func (d *Alias) listRoot() []model.Obj { + var objs []model.Obj + for k, _ := range d.pathMap { + obj := model.Object{ + Name: k, + IsFolder: true, + Modified: d.Modified, + } + objs = append(objs, &obj) + } + return objs +} + +// do others that not defined in Driver interface +func getPair(path string) (string, string) { + //path = strings.TrimSpace(path) + if strings.Contains(path, ":") { + pair := strings.SplitN(path, ":", 2) + if !strings.Contains(pair[0], "/") { + return pair[0], pair[1] + } + } + return stdpath.Base(path), path +} + +func getRootAndPath(path string) (string, string) { + path = strings.TrimPrefix(path, "/") + parts := strings.SplitN(path, "/", 2) + if len(parts) == 1 { + return parts[0], "" + } + return parts[0], parts[1] +} + +func (d *Alias) get(ctx context.Context, path string, dst, sub string) (model.Obj, error) { + obj, err := fs.Get(ctx, stdpath.Join(dst, sub)) + if err != nil { + return nil, err + } + return &model.Object{ + Path: path, + Name: obj.GetName(), + Size: obj.GetSize(), + Modified: obj.ModTime(), + IsFolder: obj.IsDir(), + }, nil +} + +func (d *Alias) list(ctx context.Context, dst, sub string) ([]model.Obj, error) { + objs, err := fs.List(ctx, stdpath.Join(dst, sub)) + // the obj must implement the model.SetPath interface + // return objs, err + if err != nil { + return nil, err + } + return utils.SliceConvert(objs, func(obj model.Obj) (model.Obj, error) { + return &model.Object{ + Name: obj.GetName(), + Size: obj.GetSize(), + Modified: obj.ModTime(), + IsFolder: obj.IsDir(), + }, nil + }) +} + +func (d *Alias) link(ctx context.Context, dst, sub string, args model.LinkArgs) (*model.Link, error) { + link, _, err := fs.Link(ctx, stdpath.Join(dst, sub), args) + return link, err +} diff --git a/drivers/all.go b/drivers/all.go index 9fe2faaa2b9..eb5e472050d 100644 --- a/drivers/all.go +++ b/drivers/all.go @@ -6,6 +6,7 @@ import ( _ "github.com/alist-org/alist/v3/drivers/139" _ "github.com/alist-org/alist/v3/drivers/189" _ "github.com/alist-org/alist/v3/drivers/189pc" + _ "github.com/alist-org/alist/v3/drivers/alias" _ "github.com/alist-org/alist/v3/drivers/alist_v2" _ "github.com/alist-org/alist/v3/drivers/alist_v3" _ "github.com/alist-org/alist/v3/drivers/aliyundrive" diff --git a/drivers/template/driver.go b/drivers/template/driver.go index e067b81d88f..bc22b928e64 100644 --- a/drivers/template/driver.go +++ b/drivers/template/driver.go @@ -32,42 +32,42 @@ func (d *Template) Drop(ctx context.Context) error { } func (d *Template) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) { - // TODO return the files list + // TODO return the files list, required return nil, errs.NotImplement } func (d *Template) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) { - // TODO return link of file + // TODO return link of file, required return nil, errs.NotImplement } func (d *Template) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error { - // TODO create folder + // TODO create folder, optional return errs.NotImplement } func (d *Template) Move(ctx context.Context, srcObj, dstDir model.Obj) error { - // TODO move obj + // TODO move obj, optional return errs.NotImplement } func (d *Template) Rename(ctx context.Context, srcObj model.Obj, newName string) error { - // TODO rename obj + // TODO rename obj, optional return errs.NotImplement } func (d *Template) Copy(ctx context.Context, srcObj, dstDir model.Obj) error { - // TODO copy obj + // TODO copy obj, optional return errs.NotImplement } func (d *Template) Remove(ctx context.Context, obj model.Obj) error { - // TODO remove obj + // TODO remove obj, optional return errs.NotImplement } func (d *Template) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error { - // TODO upload file + // TODO upload file, optional return errs.NotImplement } diff --git a/drivers/template/meta.go b/drivers/template/meta.go index 15780ac01a2..45aeb85ac58 100644 --- a/drivers/template/meta.go +++ b/drivers/template/meta.go @@ -14,14 +14,17 @@ type Addition struct { } var config = driver.Config{ - Name: "Template", - LocalSort: false, - OnlyLocal: false, - OnlyProxy: false, - NoCache: false, - NoUpload: false, - NeedMs: false, - DefaultRoot: "root, / or other", + Name: "Template", + LocalSort: false, + OnlyLocal: false, + OnlyProxy: false, + NoCache: false, + NoUpload: false, + NeedMs: false, + DefaultRoot: "root, / or other", + CheckStatus: false, + Alert: "", + NoOverwriteUpload: false, } func init() {