diff --git a/drivers/local/driver.go b/drivers/local/driver.go index b764e27f..cb7503b7 100644 --- a/drivers/local/driver.go +++ b/drivers/local/driver.go @@ -36,12 +36,12 @@ func (d *Driver) GetAddition() driver.Additional { return d.Addition } -func (d *Driver) List(ctx context.Context, path string) ([]driver.FileInfo, error) { +func (d *Driver) List(ctx context.Context, path string) ([]model.FileInfo, error) { //TODO implement me panic("implement me") } -func (d *Driver) Link(ctx context.Context, path string, args driver.LinkArgs) (*driver.Link, error) { +func (d *Driver) Link(ctx context.Context, path string, args model.LinkArgs) (*model.Link, error) { //TODO implement me panic("implement me") } @@ -76,7 +76,7 @@ func (d *Driver) Remove(ctx context.Context, path string) error { panic("implement me") } -func (d *Driver) Put(ctx context.Context, parentPath string, stream driver.FileStream) error { +func (d *Driver) Put(ctx context.Context, parentPath string, stream model.FileStreamer) error { //TODO implement me panic("implement me") } diff --git a/internal/driver/driver.go b/internal/driver/driver.go index 3f7f85ef..9b556ebb 100644 --- a/internal/driver/driver.go +++ b/internal/driver/driver.go @@ -2,6 +2,7 @@ package driver import ( "context" + "github.com/alist-org/alist/v3/internal/model" ) @@ -28,8 +29,8 @@ type Other interface { } type Reader interface { - List(ctx context.Context, path string) ([]FileInfo, error) - Link(ctx context.Context, path string, args LinkArgs) (*Link, error) + List(ctx context.Context, path string) ([]model.FileInfo, error) + Link(ctx context.Context, path string, args model.LinkArgs) (*model.Link, error) //Get(ctx context.Context, path string) (FileInfo, error) // maybe not need } @@ -39,5 +40,5 @@ type Writer interface { Rename(ctx context.Context, srcPath, dstName string) error Copy(ctx context.Context, srcPath, dstPath string) error Remove(ctx context.Context, path string) error - Put(ctx context.Context, parentPath string, stream FileStream) error + Put(ctx context.Context, parentPath string, stream model.FileStreamer) error } diff --git a/internal/fs/read.go b/internal/fs/read.go index 0eab1a02..d71bd612 100644 --- a/internal/fs/read.go +++ b/internal/fs/read.go @@ -2,20 +2,20 @@ package fs import ( "context" - "github.com/alist-org/alist/v3/internal/driver" + stdpath "path" + "time" + "github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/operations" "github.com/alist-org/alist/v3/pkg/utils" "github.com/pkg/errors" log "github.com/sirupsen/logrus" - stdpath "path" - "time" ) // List files // TODO: hide // TODO: sort -func List(ctx context.Context, path string) ([]driver.FileInfo, error) { +func List(ctx context.Context, path string) ([]model.FileInfo, error) { account, actualPath, err := operations.GetAccountAndActualPath(path) virtualFiles := operations.GetAccountVirtualFilesByPath(path) if err != nil { @@ -40,7 +40,7 @@ func List(ctx context.Context, path string) ([]driver.FileInfo, error) { return files, nil } -func Get(ctx context.Context, path string) (driver.FileInfo, error) { +func Get(ctx context.Context, path string) (model.FileInfo, error) { path = utils.StandardizationPath(path) // maybe a virtual file if path != "/" { @@ -67,7 +67,7 @@ func Get(ctx context.Context, path string) (driver.FileInfo, error) { return operations.Get(ctx, account, actualPath) } -func Link(ctx context.Context, path string, args driver.LinkArgs) (*driver.Link, error) { +func Link(ctx context.Context, path string, args model.LinkArgs) (*model.Link, error) { account, actualPath, err := operations.GetAccountAndActualPath(path) if err != nil { return nil, errors.WithMessage(err, "failed get account") diff --git a/internal/fs/write.go b/internal/fs/write.go index d144116e..36152557 100644 --- a/internal/fs/write.go +++ b/internal/fs/write.go @@ -2,7 +2,9 @@ package fs import ( "context" + "github.com/alist-org/alist/v3/internal/driver" + "github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/operations" "github.com/pkg/errors" ) @@ -39,7 +41,7 @@ func Rename(ctx context.Context, account driver.Driver, srcPath, dstName string) } // Copy if in an account, call move method -// TODO: if not, add copy task +// if not, add copy task func Copy(ctx context.Context, account driver.Driver, srcPath, dstPath string) error { srcAccount, srcActualPath, err := operations.GetAccountAndActualPath(srcPath) if err != nil { @@ -49,9 +51,16 @@ func Copy(ctx context.Context, account driver.Driver, srcPath, dstPath string) e if err != nil { return errors.WithMessage(err, "failed get dst account") } + // copy if in an account, just call driver.Copy if srcAccount.GetAccount() == dstAccount.GetAccount() { return operations.Copy(ctx, account, srcActualPath, dstActualPath) } + // not in an account, add copy task + srcFile, err := operations.Get(ctx, srcAccount, srcActualPath) + if srcFile.IsDir() { + // TODO: recursive copy + return nil + } // TODO: add copy task, maybe like this: // operations.Link(ctx,srcAccount,srcActualPath,args) // get a Reader from link @@ -68,7 +77,7 @@ func Remove(ctx context.Context, account driver.Driver, path string) error { return operations.Remove(ctx, account, actualPath) } -func Put(ctx context.Context, account driver.Driver, parentPath string, file driver.FileStream) error { +func Put(ctx context.Context, account driver.Driver, parentPath string, file model.FileStreamer) error { account, actualParentPath, err := operations.GetAccountAndActualPath(parentPath) if err != nil { return errors.WithMessage(err, "failed get account") diff --git a/internal/driver/file.go b/internal/model/ifile.go similarity index 85% rename from internal/driver/file.go rename to internal/model/ifile.go index 92647ef0..4a8363af 100644 --- a/internal/driver/file.go +++ b/internal/model/ifile.go @@ -1,4 +1,4 @@ -package driver +package model import ( "io" @@ -12,7 +12,7 @@ type FileInfo interface { IsDir() bool } -type FileStream interface { +type FileStreamer interface { io.ReadCloser FileInfo GetMimetype() string diff --git a/internal/driver/link.go b/internal/model/link.go similarity index 82% rename from internal/driver/link.go rename to internal/model/link.go index 9dcc91a3..c660c718 100644 --- a/internal/driver/link.go +++ b/internal/model/link.go @@ -1,4 +1,4 @@ -package driver +package model import ( "io" @@ -16,6 +16,6 @@ type Link struct { Header http.Header // needed header Data io.ReadCloser // return file reader directly Status int // status maybe 200 or 206, etc - FilePath string // local file, return the filepath + FilePath *string // local file, return the filepath Expiration *time.Duration // url expiration time } diff --git a/internal/model/stream.go b/internal/model/stream.go new file mode 100644 index 00000000..dcbcdb00 --- /dev/null +++ b/internal/model/stream.go @@ -0,0 +1,15 @@ +package model + +import ( + "io" +) + +type FileStream struct { + FileInfo + io.ReadCloser + Mimetype string +} + +func (f FileStream) GetMimetype() string { + return f.Mimetype +} diff --git a/internal/operations/account.go b/internal/operations/account.go index 54772702..3a4352f7 100644 --- a/internal/operations/account.go +++ b/internal/operations/account.go @@ -136,8 +136,8 @@ func getAccountsByPath(path string) []driver.Driver { // GetAccountVirtualFilesByPath Obtain the virtual file generated by the account according to the path // for example, there are: /a/b,/a/c,/a/d/e,/a/b.balance1,/av // GetAccountVirtualFilesByPath(/a) => b,c,d -func GetAccountVirtualFilesByPath(prefix string) []driver.FileInfo { - files := make([]driver.FileInfo, 0) +func GetAccountVirtualFilesByPath(prefix string) []model.FileInfo { + files := make([]model.FileInfo, 0) accounts := accountsMap.Values() sort.Slice(accounts, func(i, j int) bool { if accounts[i].GetAccount().Index == accounts[j].GetAccount().Index { diff --git a/internal/operations/fs.go b/internal/operations/fs.go index 5ecc7283..df013609 100644 --- a/internal/operations/fs.go +++ b/internal/operations/fs.go @@ -15,11 +15,11 @@ import ( // In order to facilitate adding some other things before and after file operations -var filesCache = cache.NewMemCache(cache.WithShards[[]driver.FileInfo](64)) -var filesG singleflight.Group[[]driver.FileInfo] +var filesCache = cache.NewMemCache(cache.WithShards[[]model.FileInfo](64)) +var filesG singleflight.Group[[]model.FileInfo] // List files in storage, not contains virtual file -func List(ctx context.Context, account driver.Driver, path string) ([]driver.FileInfo, error) { +func List(ctx context.Context, account driver.Driver, path string) ([]model.FileInfo, error) { if account.Config().NoCache { return account.List(ctx, path) } @@ -27,19 +27,19 @@ func List(ctx context.Context, account driver.Driver, path string) ([]driver.Fil if files, ok := filesCache.Get(key); ok { return files, nil } - files, err, _ := filesG.Do(key, func() ([]driver.FileInfo, error) { + files, err, _ := filesG.Do(key, func() ([]model.FileInfo, error) { files, err := account.List(ctx, path) if err != nil { return nil, errors.WithMessage(err, "failed to list files") } // TODO: get duration from global config or account's config - filesCache.Set(key, files, cache.WithEx[[]driver.FileInfo](time.Minute*30)) + filesCache.Set(key, files, cache.WithEx[[]model.FileInfo](time.Minute*30)) return files, nil }) return files, err } -func Get(ctx context.Context, account driver.Driver, path string) (driver.FileInfo, error) { +func Get(ctx context.Context, account driver.Driver, path string) (model.FileInfo, error) { if r, ok := account.GetAddition().(driver.RootFolderId); ok && utils.PathEqual(path, "/") { return model.FileWithId{ Id: r.GetRootFolderId(), @@ -72,22 +72,22 @@ func Get(ctx context.Context, account driver.Driver, path string) (driver.FileIn return nil, errors.WithStack(driver.ErrorObjectNotFound) } -var linkCache = cache.NewMemCache(cache.WithShards[*driver.Link](16)) -var linkG singleflight.Group[*driver.Link] +var linkCache = cache.NewMemCache(cache.WithShards[*model.Link](16)) +var linkG singleflight.Group[*model.Link] // Link get link, if is an url. should have an expiry time -func Link(ctx context.Context, account driver.Driver, path string, args driver.LinkArgs) (*driver.Link, error) { +func Link(ctx context.Context, account driver.Driver, path string, args model.LinkArgs) (*model.Link, error) { key := stdpath.Join(account.GetAccount().VirtualPath, path) if link, ok := linkCache.Get(key); ok { return link, nil } - fn := func() (*driver.Link, error) { + fn := func() (*model.Link, error) { link, err := account.Link(ctx, path, args) if err != nil { return nil, errors.WithMessage(err, "failed get link") } if link.Expiration != nil { - linkCache.Set(key, link, cache.WithEx[*driver.Link](*link.Expiration)) + linkCache.Set(key, link, cache.WithEx[*model.Link](*link.Expiration)) } return link, nil } @@ -116,6 +116,6 @@ func Remove(ctx context.Context, account driver.Driver, path string) error { return account.Remove(ctx, path) } -func Put(ctx context.Context, account driver.Driver, parentPath string, file driver.FileStream) error { +func Put(ctx context.Context, account driver.Driver, parentPath string, file model.FileStreamer) error { return account.Put(ctx, parentPath, file) } diff --git a/internal/task/task.go b/internal/task/task.go index 6e5003f1..24c25785 100644 --- a/internal/task/task.go +++ b/internal/task/task.go @@ -4,9 +4,9 @@ package task import "context" type Task struct { - Name string - Func func(context.Context) error - Status string - Error error - Progress int + Name string + Func func(context.Context) error + Status string + Error error + Finish bool }