refactor: change driver interface
This commit is contained in:
parent
d9eb188b7a
commit
09ef7c7106
@ -18,11 +18,6 @@ type Scheme struct {
|
|||||||
KeyFile string `json:"key_file" env:"KEY_FILE"`
|
KeyFile string `json:"key_file" env:"KEY_FILE"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CacheConfig struct {
|
|
||||||
Expiration int64 `json:"expiration" env:"CACHE_EXPIRATION"`
|
|
||||||
CleanupInterval int64 `json:"cleanup_interval" env:"CLEANUP_INTERVAL"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type LogConfig struct {
|
type LogConfig struct {
|
||||||
Enable bool `json:"enable" env:"log_enable"`
|
Enable bool `json:"enable" env:"log_enable"`
|
||||||
Path string `json:"path" env:"LOG_PATH"`
|
Path string `json:"path" env:"LOG_PATH"`
|
||||||
@ -35,10 +30,10 @@ type Config struct {
|
|||||||
Force bool `json:"force"`
|
Force bool `json:"force"`
|
||||||
Address string `json:"address" env:"ADDR"`
|
Address string `json:"address" env:"ADDR"`
|
||||||
Port int `json:"port" env:"PORT"`
|
Port int `json:"port" env:"PORT"`
|
||||||
|
CaCheExpiration int `json:"cache_expiration" env:"CACHE_EXPIRATION"`
|
||||||
Assets string `json:"assets" env:"ASSETS"`
|
Assets string `json:"assets" env:"ASSETS"`
|
||||||
Database Database `json:"database"`
|
Database Database `json:"database"`
|
||||||
Scheme Scheme `json:"scheme"`
|
Scheme Scheme `json:"scheme"`
|
||||||
Cache CacheConfig `json:"cache"`
|
|
||||||
TempDir string `json:"temp_dir" env:"TEMP_DIR"`
|
TempDir string `json:"temp_dir" env:"TEMP_DIR"`
|
||||||
Log LogConfig `json:"log"`
|
Log LogConfig `json:"log"`
|
||||||
}
|
}
|
||||||
@ -55,10 +50,7 @@ func DefaultConfig() *Config {
|
|||||||
TablePrefix: "x_",
|
TablePrefix: "x_",
|
||||||
DBFile: "data/data.db",
|
DBFile: "data/data.db",
|
||||||
},
|
},
|
||||||
Cache: CacheConfig{
|
CaCheExpiration: 30,
|
||||||
Expiration: 60,
|
|
||||||
CleanupInterval: 120,
|
|
||||||
},
|
|
||||||
Log: LogConfig{
|
Log: LogConfig{
|
||||||
Enable: true,
|
Enable: true,
|
||||||
Path: "log/%Y-%m-%d-%H:%M.log",
|
Path: "log/%Y-%m-%d-%H:%M.log",
|
||||||
|
@ -44,12 +44,42 @@ func (d *Driver) GetAddition() driver.Additional {
|
|||||||
return d.Addition
|
return d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) List(ctx context.Context, path string) ([]model.FileInfo, error) {
|
func (d *Driver) List(ctx context.Context, dir model.Object) ([]model.Object, error) {
|
||||||
//TODO implement me
|
//TODO implement me
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) Link(ctx context.Context, path string, args model.LinkArgs) (*model.Link, error) {
|
func (d *Driver) Link(ctx context.Context, file model.Object, args model.LinkArgs) (*model.Link, error) {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Driver) MakeDir(ctx context.Context, parentDir model.Object, dirName string) error {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Driver) Move(ctx context.Context, srcObject, dstDir model.Object) error {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Driver) Rename(ctx context.Context, srcObject model.Object, newName string) error {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Driver) Copy(ctx context.Context, srcObject, dstDir model.Object) error {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Driver) Remove(ctx context.Context, object model.Object) error {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Driver) Put(ctx context.Context, parentDir model.Object, stream model.FileStreamer) error {
|
||||||
//TODO implement me
|
//TODO implement me
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
@ -59,34 +89,4 @@ func (d Driver) Other(ctx context.Context, data interface{}) (interface{}, error
|
|||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) MakeDir(ctx context.Context, path string) error {
|
|
||||||
//TODO implement me
|
|
||||||
panic("implement me")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Driver) Move(ctx context.Context, src, dst string) error {
|
|
||||||
//TODO implement me
|
|
||||||
panic("implement me")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Driver) Rename(ctx context.Context, src, dst string) error {
|
|
||||||
//TODO implement me
|
|
||||||
panic("implement me")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Driver) Copy(ctx context.Context, src, dst string) error {
|
|
||||||
//TODO implement me
|
|
||||||
panic("implement me")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Driver) Remove(ctx context.Context, path string) error {
|
|
||||||
//TODO implement me
|
|
||||||
panic("implement me")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Driver) Put(ctx context.Context, parentPath string, stream model.FileStreamer) error {
|
|
||||||
//TODO implement me
|
|
||||||
panic("implement me")
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ driver.Driver = (*Driver)(nil)
|
var _ driver.Driver = (*Driver)(nil)
|
||||||
|
@ -29,16 +29,22 @@ type Other interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Reader interface {
|
type Reader interface {
|
||||||
List(ctx context.Context, path string) ([]model.FileInfo, error)
|
List(ctx context.Context, dir model.Object) ([]model.Object, error)
|
||||||
Link(ctx context.Context, path string, args model.LinkArgs) (*model.Link, error)
|
Link(ctx context.Context, file model.Object, args model.LinkArgs) (*model.Link, error)
|
||||||
//Get(ctx context.Context, path string) (FileInfo, error) // maybe not need
|
//Get(ctx context.Context, path string) (FileInfo, error) // maybe not need
|
||||||
}
|
}
|
||||||
|
|
||||||
type Writer interface {
|
type Writer interface {
|
||||||
MakeDir(ctx context.Context, path string) error
|
// MakeDir make a folder named `dirName` in `parentDir`
|
||||||
Move(ctx context.Context, srcPath, dstPath string) error
|
MakeDir(ctx context.Context, parentDir model.Object, dirName string) error
|
||||||
Rename(ctx context.Context, srcPath, dstName string) error
|
// Move move `srcObject` to `dstDir`
|
||||||
Copy(ctx context.Context, srcPath, dstPath string) error
|
Move(ctx context.Context, srcObject, dstDir model.Object) error
|
||||||
Remove(ctx context.Context, path string) error
|
// Rename rename `srcObject` to `newName`
|
||||||
Put(ctx context.Context, parentPath string, stream model.FileStreamer) error
|
Rename(ctx context.Context, srcObject model.Object, newName string) error
|
||||||
|
// Copy copy `srcObject` to `dstDir`
|
||||||
|
Copy(ctx context.Context, srcObject, dstDir model.Object) error
|
||||||
|
// Remove remove `object`
|
||||||
|
Remove(ctx context.Context, object model.Object) error
|
||||||
|
// Put put `stream` to `parentDir`
|
||||||
|
Put(ctx context.Context, parentDir model.Object, stream model.FileStreamer) error
|
||||||
}
|
}
|
||||||
|
5
internal/fs/fs.go
Normal file
5
internal/fs/fs.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package fs
|
||||||
|
|
||||||
|
// the param named path of functions in this package is a virtual path
|
||||||
|
// So, the purpose of this package is to convert virtual path to actual path
|
||||||
|
// then pass the actual path to the operations package
|
@ -15,7 +15,7 @@ import (
|
|||||||
// List files
|
// List files
|
||||||
// TODO: hide
|
// TODO: hide
|
||||||
// TODO: sort
|
// TODO: sort
|
||||||
func List(ctx context.Context, path string) ([]model.FileInfo, error) {
|
func List(ctx context.Context, path string) ([]model.Object, error) {
|
||||||
account, actualPath, err := operations.GetAccountAndActualPath(path)
|
account, actualPath, err := operations.GetAccountAndActualPath(path)
|
||||||
virtualFiles := operations.GetAccountVirtualFilesByPath(path)
|
virtualFiles := operations.GetAccountVirtualFilesByPath(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -40,7 +40,7 @@ func List(ctx context.Context, path string) ([]model.FileInfo, error) {
|
|||||||
return files, nil
|
return files, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Get(ctx context.Context, path string) (model.FileInfo, error) {
|
func Get(ctx context.Context, path string) (model.Object, error) {
|
||||||
path = utils.StandardizationPath(path)
|
path = utils.StandardizationPath(path)
|
||||||
// maybe a virtual file
|
// maybe a virtual file
|
||||||
if path != "/" {
|
if path != "/" {
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func containsByName(files []model.FileInfo, file model.FileInfo) bool {
|
func containsByName(files []model.Object, file model.Object) bool {
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
if f.GetName() == file.GetName() {
|
if f.GetName() == file.GetName() {
|
||||||
return true
|
return true
|
||||||
@ -23,7 +23,7 @@ func containsByName(files []model.FileInfo, file model.FileInfo) bool {
|
|||||||
|
|
||||||
var httpClient = &http.Client{}
|
var httpClient = &http.Client{}
|
||||||
|
|
||||||
func getFileStreamFromLink(file model.FileInfo, link *model.Link) (model.FileStreamer, error) {
|
func getFileStreamFromLink(file model.Object, link *model.Link) (model.FileStreamer, error) {
|
||||||
var rc io.ReadCloser
|
var rc io.ReadCloser
|
||||||
mimetype := mime.TypeByExtension(stdpath.Ext(file.GetName()))
|
mimetype := mime.TypeByExtension(stdpath.Ext(file.GetName()))
|
||||||
if link.Data != nil {
|
if link.Data != nil {
|
||||||
@ -57,7 +57,7 @@ func getFileStreamFromLink(file model.FileInfo, link *model.Link) (model.FileStr
|
|||||||
mimetype = "application/octet-stream"
|
mimetype = "application/octet-stream"
|
||||||
}
|
}
|
||||||
stream := model.FileStream{
|
stream := model.FileStream{
|
||||||
FileInfo: file,
|
Object: file,
|
||||||
ReadCloser: rc,
|
ReadCloser: rc,
|
||||||
Mimetype: mimetype,
|
Mimetype: mimetype,
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package model
|
|||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type File struct {
|
type File struct {
|
||||||
|
ID string
|
||||||
Name string
|
Name string
|
||||||
Size uint64
|
Size uint64
|
||||||
Modified time.Time
|
Modified time.Time
|
||||||
@ -25,7 +26,6 @@ func (f File) IsDir() bool {
|
|||||||
return f.IsFolder
|
return f.IsFolder
|
||||||
}
|
}
|
||||||
|
|
||||||
type FileWithId struct {
|
func (f File) GetID() string {
|
||||||
Id string
|
return f.ID
|
||||||
File
|
|
||||||
}
|
}
|
||||||
|
@ -5,16 +5,17 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FileInfo interface {
|
type Object interface {
|
||||||
GetSize() uint64
|
GetSize() uint64
|
||||||
GetName() string
|
GetName() string
|
||||||
ModTime() time.Time
|
ModTime() time.Time
|
||||||
IsDir() bool
|
IsDir() bool
|
||||||
|
GetID() string
|
||||||
}
|
}
|
||||||
|
|
||||||
type FileStreamer interface {
|
type FileStreamer interface {
|
||||||
io.ReadCloser
|
io.ReadCloser
|
||||||
FileInfo
|
Object
|
||||||
GetMimetype() string
|
GetMimetype() string
|
||||||
}
|
}
|
||||||
|
|
@ -5,7 +5,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type FileStream struct {
|
type FileStream struct {
|
||||||
FileInfo
|
Object
|
||||||
io.ReadCloser
|
io.ReadCloser
|
||||||
Mimetype string
|
Mimetype string
|
||||||
}
|
}
|
||||||
|
@ -136,8 +136,8 @@ func getAccountsByPath(path string) []driver.Driver {
|
|||||||
// GetAccountVirtualFilesByPath Obtain the virtual file generated by the account according to the path
|
// 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
|
// for example, there are: /a/b,/a/c,/a/d/e,/a/b.balance1,/av
|
||||||
// GetAccountVirtualFilesByPath(/a) => b,c,d
|
// GetAccountVirtualFilesByPath(/a) => b,c,d
|
||||||
func GetAccountVirtualFilesByPath(prefix string) []model.FileInfo {
|
func GetAccountVirtualFilesByPath(prefix string) []model.Object {
|
||||||
files := make([]model.FileInfo, 0)
|
files := make([]model.Object, 0)
|
||||||
accounts := accountsMap.Values()
|
accounts := accountsMap.Values()
|
||||||
sort.Slice(accounts, func(i, j int) bool {
|
sort.Slice(accounts, func(i, j int) bool {
|
||||||
if accounts[i].GetAccount().Index == accounts[j].GetAccount().Index {
|
if accounts[i].GetAccount().Index == accounts[j].GetAccount().Index {
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Xhofe/go-cache"
|
"github.com/Xhofe/go-cache"
|
||||||
|
"github.com/alist-org/alist/v3/conf"
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/pkg/singleflight"
|
"github.com/alist-org/alist/v3/pkg/singleflight"
|
||||||
@ -15,50 +16,57 @@ import (
|
|||||||
|
|
||||||
// In order to facilitate adding some other things before and after file operations
|
// In order to facilitate adding some other things before and after file operations
|
||||||
|
|
||||||
var filesCache = cache.NewMemCache(cache.WithShards[[]model.FileInfo](64))
|
var filesCache = cache.NewMemCache(cache.WithShards[[]model.Object](64))
|
||||||
var filesG singleflight.Group[[]model.FileInfo]
|
var filesG singleflight.Group[[]model.Object]
|
||||||
|
|
||||||
// List files in storage, not contains virtual file
|
// List files in storage, not contains virtual file
|
||||||
func List(ctx context.Context, account driver.Driver, path string) ([]model.FileInfo, error) {
|
func List(ctx context.Context, account driver.Driver, path string) ([]model.Object, error) {
|
||||||
|
dir, err := Get(ctx, account, path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.WithMessage(err, "failed get dir")
|
||||||
|
}
|
||||||
if account.Config().NoCache {
|
if account.Config().NoCache {
|
||||||
return account.List(ctx, path)
|
return account.List(ctx, dir)
|
||||||
}
|
}
|
||||||
key := stdpath.Join(account.GetAccount().VirtualPath, path)
|
key := stdpath.Join(account.GetAccount().VirtualPath, path)
|
||||||
if files, ok := filesCache.Get(key); ok {
|
if files, ok := filesCache.Get(key); ok {
|
||||||
return files, nil
|
return files, nil
|
||||||
}
|
}
|
||||||
files, err, _ := filesG.Do(key, func() ([]model.FileInfo, error) {
|
files, err, _ := filesG.Do(key, func() ([]model.Object, error) {
|
||||||
files, err := account.List(ctx, path)
|
files, err := account.List(ctx, dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithMessage(err, "failed to list files")
|
return nil, errors.WithMessage(err, "failed to list files")
|
||||||
}
|
}
|
||||||
// TODO: get duration from global config or account's config
|
// TODO: maybe can get duration from account's config
|
||||||
filesCache.Set(key, files, cache.WithEx[[]model.FileInfo](time.Minute*30))
|
filesCache.Set(key, files, cache.WithEx[[]model.Object](time.Minute*time.Duration(conf.Conf.CaCheExpiration)))
|
||||||
return files, nil
|
return files, nil
|
||||||
})
|
})
|
||||||
return files, err
|
return files, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func Get(ctx context.Context, account driver.Driver, path string) (model.FileInfo, error) {
|
// Get get object from list of files
|
||||||
if r, ok := account.GetAddition().(driver.RootFolderId); ok && utils.PathEqual(path, "/") {
|
// TODO: maybe should set object ID with path here
|
||||||
return model.FileWithId{
|
func Get(ctx context.Context, account driver.Driver, path string) (model.Object, error) {
|
||||||
Id: r.GetRootFolderId(),
|
// is root folder
|
||||||
File: model.File{
|
if r, ok := account.GetAddition().(driver.IRootFolderId); ok && utils.PathEqual(path, "/") {
|
||||||
|
return model.File{
|
||||||
|
ID: r.GetRootFolderId(),
|
||||||
Name: "root",
|
Name: "root",
|
||||||
Size: 0,
|
Size: 0,
|
||||||
Modified: account.GetAccount().Modified,
|
Modified: account.GetAccount().Modified,
|
||||||
IsFolder: true,
|
IsFolder: true,
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
if r, ok := account.GetAddition().(driver.IRootFolderPath); ok && utils.PathEqual(path, r.GetRootFolderPath()) {
|
if r, ok := account.GetAddition().(driver.IRootFolderPath); ok && utils.PathEqual(path, r.GetRootFolderPath()) {
|
||||||
return model.File{
|
return model.File{
|
||||||
|
ID: r.GetRootFolderPath(),
|
||||||
Name: "root",
|
Name: "root",
|
||||||
Size: 0,
|
Size: 0,
|
||||||
Modified: account.GetAccount().Modified,
|
Modified: account.GetAccount().Modified,
|
||||||
IsFolder: true,
|
IsFolder: true,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
// not root folder
|
||||||
dir, name := stdpath.Split(path)
|
dir, name := stdpath.Split(path)
|
||||||
files, err := List(ctx, account, dir)
|
files, err := List(ctx, account, dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -82,7 +90,11 @@ func Link(ctx context.Context, account driver.Driver, path string, args model.Li
|
|||||||
return link, nil
|
return link, nil
|
||||||
}
|
}
|
||||||
fn := func() (*model.Link, error) {
|
fn := func() (*model.Link, error) {
|
||||||
link, err := account.Link(ctx, path, args)
|
file, err := Get(ctx, account, path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.WithMessage(err, "failed to get file")
|
||||||
|
}
|
||||||
|
link, err := account.Link(ctx, file, args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithMessage(err, "failed get link")
|
return nil, errors.WithMessage(err, "failed get link")
|
||||||
}
|
}
|
||||||
@ -98,54 +110,81 @@ func Link(ctx context.Context, account driver.Driver, path string, args model.Li
|
|||||||
func MakeDir(ctx context.Context, account driver.Driver, path string) error {
|
func MakeDir(ctx context.Context, account driver.Driver, path string) error {
|
||||||
// check if dir exists
|
// check if dir exists
|
||||||
f, err := Get(ctx, account, path)
|
f, err := Get(ctx, account, path)
|
||||||
if f != nil && f.IsDir() {
|
if err != nil {
|
||||||
return nil
|
if driver.IsErrObjectNotFound(err) {
|
||||||
}
|
parentPath, dirName := stdpath.Split(path)
|
||||||
if err != nil && !driver.IsErrObjectNotFound(err) {
|
|
||||||
return errors.WithMessage(err, "failed to check if dir exists")
|
|
||||||
}
|
|
||||||
parentPath := stdpath.Dir(path)
|
|
||||||
err = MakeDir(ctx, account, parentPath)
|
err = MakeDir(ctx, account, parentPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithMessagef(err, "failed to make parent dir [%s]", parentPath)
|
return errors.WithMessagef(err, "failed to make parent dir [%s]", parentPath)
|
||||||
}
|
}
|
||||||
return account.MakeDir(ctx, path)
|
parentDir, err := Get(ctx, account, parentPath)
|
||||||
|
// this should not happen
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithMessagef(err, "failed to get parent dir [%s]", parentPath)
|
||||||
|
}
|
||||||
|
return account.MakeDir(ctx, parentDir, dirName)
|
||||||
|
} else {
|
||||||
|
return errors.WithMessage(err, "failed to check if dir exists")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// dir exists
|
||||||
|
if f.IsDir() {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
// dir to make is a file
|
||||||
|
return errors.New("file exists")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Move(ctx context.Context, account driver.Driver, srcPath, dstPath string) error {
|
func Move(ctx context.Context, account driver.Driver, srcPath, dstPath string) error {
|
||||||
return account.Move(ctx, srcPath, dstPath)
|
srcObject, err := Get(ctx, account, srcPath)
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithMessage(err, "failed to get src object")
|
||||||
|
}
|
||||||
|
dstDir, err := Get(ctx, account, stdpath.Dir(dstPath))
|
||||||
|
return account.Move(ctx, srcObject, dstDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Rename(ctx context.Context, account driver.Driver, srcPath, dstName string) error {
|
func Rename(ctx context.Context, account driver.Driver, srcPath, dstName string) error {
|
||||||
return account.Rename(ctx, srcPath, dstName)
|
srcObject, err := Get(ctx, account, srcPath)
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithMessage(err, "failed to get src object")
|
||||||
|
}
|
||||||
|
return account.Rename(ctx, srcObject, dstName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy Just copy file[s] in an account
|
// Copy Just copy file[s] in an account
|
||||||
func Copy(ctx context.Context, account driver.Driver, srcPath, dstPath string) error {
|
func Copy(ctx context.Context, account driver.Driver, srcPath, dstPath string) error {
|
||||||
return account.Copy(ctx, srcPath, dstPath)
|
srcObject, err := Get(ctx, account, srcPath)
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithMessage(err, "failed to get src object")
|
||||||
|
}
|
||||||
|
dstDir, err := Get(ctx, account, stdpath.Dir(dstPath))
|
||||||
|
return account.Copy(ctx, srcObject, dstDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Remove(ctx context.Context, account driver.Driver, path string) error {
|
func Remove(ctx context.Context, account driver.Driver, path string) error {
|
||||||
return account.Remove(ctx, path)
|
object, err := Get(ctx, account, path)
|
||||||
|
if err != nil {
|
||||||
|
// if object not found, it's ok
|
||||||
|
if driver.IsErrObjectNotFound(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.WithMessage(err, "failed to get object")
|
||||||
|
}
|
||||||
|
return account.Remove(ctx, object)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Put(ctx context.Context, account driver.Driver, parentPath string, file model.FileStreamer) error {
|
func Put(ctx context.Context, account driver.Driver, parentPath string, file model.FileStreamer) error {
|
||||||
f, err := Get(ctx, account, parentPath)
|
err := MakeDir(ctx, account, parentPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// if parent dir not exists, create it
|
return errors.WithMessagef(err, "failed to make dir [%s]", parentPath)
|
||||||
if driver.IsErrObjectNotFound(err) {
|
}
|
||||||
err = MakeDir(ctx, account, parentPath)
|
parentDir, err := Get(ctx, account, parentPath)
|
||||||
|
// this should not happen
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithMessagef(err, "failed to make parent dir [%s]", parentPath)
|
return errors.WithMessagef(err, "failed to get dir [%s]", parentPath)
|
||||||
}
|
}
|
||||||
} else {
|
return account.Put(ctx, parentDir, file)
|
||||||
return errors.WithMessage(err, "failed to get parent dir")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// object exists, check if it is a dir
|
|
||||||
if !f.IsDir() {
|
|
||||||
return errors.Errorf("object [%s] is not a dir", parentPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return account.Put(ctx, parentPath, file)
|
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
package operations
|
package operations
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
stdpath "path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func ActualPath(account driver.Additional, rawPath string) string {
|
func ActualPath(account driver.Additional, rawPath string) string {
|
||||||
if i, ok := account.(driver.IRootFolderPath); ok {
|
if i, ok := account.(driver.IRootFolderPath); ok {
|
||||||
rawPath = path.Join(i.GetRootFolderPath(), rawPath)
|
rawPath = stdpath.Join(i.GetRootFolderPath(), rawPath)
|
||||||
}
|
}
|
||||||
return utils.StandardizationPath(rawPath)
|
return utils.StandardizationPath(rawPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAccountAndActualPath Get the corresponding account, and remove the virtual path prefix in path
|
// GetAccountAndActualPath Get the corresponding account
|
||||||
|
// for path: remove the virtual path prefix and join the actual root folder if exists
|
||||||
func GetAccountAndActualPath(rawPath string) (driver.Driver, string, error) {
|
func GetAccountAndActualPath(rawPath string) (driver.Driver, string, error) {
|
||||||
rawPath = utils.StandardizationPath(rawPath)
|
rawPath = utils.StandardizationPath(rawPath)
|
||||||
account := GetBalancedAccount(rawPath)
|
account := GetBalancedAccount(rawPath)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user