2022-06-15 18:58:26 +08:00
package fs
import (
"context"
2022-06-17 21:23:44 +08:00
"fmt"
"github.com/alist-org/alist/v3/pkg/task"
"github.com/alist-org/alist/v3/pkg/utils"
2022-06-15 18:58:26 +08:00
stdpath "path"
"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"
)
2022-06-17 21:38:37 +08:00
var CopyTaskManager = task . NewTaskManager ( )
2022-06-17 15:57:16 +08:00
2022-06-17 21:35:46 +08:00
// Copy if in an account, call move method
// if not, add copy task
func Copy ( ctx context . Context , account driver . Driver , srcPath , dstPath string ) ( bool , error ) {
srcAccount , srcActualPath , err := operations . GetAccountAndActualPath ( srcPath )
if err != nil {
return false , errors . WithMessage ( err , "failed get src account" )
}
dstAccount , dstActualPath , err := operations . GetAccountAndActualPath ( dstPath )
if err != nil {
return false , errors . WithMessage ( err , "failed get dst account" )
}
// copy if in an account, just call driver.Copy
if srcAccount . GetAccount ( ) == dstAccount . GetAccount ( ) {
return false , operations . Copy ( ctx , account , srcActualPath , dstActualPath )
}
// not in an account
2022-06-17 21:38:37 +08:00
CopyTaskManager . Add ( fmt . Sprintf ( "copy [%s](%s) to [%s](%s)" , srcAccount . GetAccount ( ) . VirtualPath , srcActualPath , dstAccount . GetAccount ( ) . VirtualPath , dstActualPath ) , func ( task * task . Task ) error {
2022-06-17 21:35:46 +08:00
return CopyBetween2Accounts ( task . Ctx , srcAccount , dstAccount , srcActualPath , dstActualPath , task . SetStatus )
} )
return true , nil
}
2022-06-17 21:23:44 +08:00
func CopyBetween2Accounts ( ctx context . Context , srcAccount , dstAccount driver . Driver , srcPath , dstPath string , setStatus func ( status string ) ) error {
setStatus ( "getting src object" )
srcObj , err := operations . Get ( ctx , srcAccount , srcPath )
2022-06-15 18:58:26 +08:00
if err != nil {
return errors . WithMessagef ( err , "failed get src [%s] file" , srcPath )
}
2022-06-17 21:23:44 +08:00
if srcObj . IsDir ( ) {
2022-06-17 21:30:16 +08:00
setStatus ( "src object is dir, listing objs" )
objs , err := operations . List ( ctx , srcAccount , srcPath )
2022-06-15 18:58:26 +08:00
if err != nil {
2022-06-17 21:30:16 +08:00
return errors . WithMessagef ( err , "failed list src [%s] objs" , srcPath )
2022-06-15 18:58:26 +08:00
}
2022-06-17 21:30:16 +08:00
for _ , obj := range objs {
2022-06-17 21:23:44 +08:00
if utils . IsCanceled ( ctx ) {
return nil
}
2022-06-17 21:30:16 +08:00
srcObjPath := stdpath . Join ( srcPath , obj . GetName ( ) )
dstObjPath := stdpath . Join ( dstPath , obj . GetName ( ) )
2022-06-17 21:38:37 +08:00
CopyTaskManager . Add ( fmt . Sprintf ( "copy [%s](%s) to [%s](%s)" , srcAccount . GetAccount ( ) . VirtualPath , srcObjPath , dstAccount . GetAccount ( ) . VirtualPath , dstObjPath ) , func ( task * task . Task ) error {
2022-06-17 21:30:16 +08:00
return CopyBetween2Accounts ( ctx , srcAccount , dstAccount , srcObjPath , dstObjPath , task . SetStatus )
2022-06-17 21:23:44 +08:00
} )
2022-06-15 18:58:26 +08:00
}
2022-06-17 21:23:44 +08:00
} else {
2022-06-17 21:38:37 +08:00
CopyTaskManager . Add ( fmt . Sprintf ( "copy [%s](%s) to [%s](%s)" , srcAccount . GetAccount ( ) . VirtualPath , srcPath , dstAccount . GetAccount ( ) . VirtualPath , dstPath ) , func ( task * task . Task ) error {
2022-06-17 21:23:44 +08:00
return CopyFileBetween2Accounts ( task . Ctx , srcAccount , dstAccount , srcPath , dstPath , func ( percentage float64 ) {
task . SetStatus ( fmt . Sprintf ( "uploading: %2.f%" , percentage ) )
} )
} )
}
return nil
}
func CopyFileBetween2Accounts ( ctx context . Context , srcAccount , dstAccount driver . Driver , srcPath , dstPath string , up driver . UpdateProgress ) error {
srcFile , err := operations . Get ( ctx , srcAccount , srcPath )
if err != nil {
return errors . WithMessagef ( err , "failed get src [%s] file" , srcPath )
2022-06-15 18:58:26 +08:00
}
link , err := operations . Link ( ctx , srcAccount , srcPath , model . LinkArgs { } )
if err != nil {
return errors . WithMessagef ( err , "failed get [%s] link" , srcPath )
}
stream , err := getFileStreamFromLink ( srcFile , link )
if err != nil {
return errors . WithMessagef ( err , "failed get [%s] stream" , srcPath )
}
2022-06-17 21:23:44 +08:00
return operations . Put ( ctx , dstAccount , dstPath , stream , up )
2022-06-15 18:58:26 +08:00
}