mirror of
https://github.com/tickstep/aliyunpan.git
synced 2025-01-23 14:32:14 +08:00
add sync command
This commit is contained in:
parent
d0e7715f4d
commit
f692e2d18b
102
internal/command/sync.go
Normal file
102
internal/command/sync.go
Normal file
@ -0,0 +1,102 @@
|
||||
// Copyright (c) 2020 tickstep.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/tickstep/aliyunpan/cmder"
|
||||
"github.com/tickstep/aliyunpan/internal/config"
|
||||
"github.com/tickstep/aliyunpan/internal/syncdrive"
|
||||
"github.com/tickstep/aliyunpan/internal/utils"
|
||||
"github.com/tickstep/library-go/logger"
|
||||
"github.com/urfave/cli"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func CmdSync() cli.Command {
|
||||
return cli.Command{
|
||||
Name: "sync",
|
||||
Usage: "同步备份功能(Beta)",
|
||||
UsageText: cmder.App().Name + " sync",
|
||||
Description: `
|
||||
备份功能。指定本地目录和对应的一个网盘目录,以备份文件。
|
||||
备份功能支持一下三种模式:
|
||||
1. 备份本地文件,即上传本地文件到网盘,始终保持本地文件有一个完整的备份在网盘
|
||||
2. 备份云盘文件,即下载网盘文件到本地,始终保持网盘的文件有一个完整的备份在本地
|
||||
3. 双向备份,保持网盘文件和本地文件严格一致
|
||||
|
||||
`,
|
||||
Category: "阿里云盘",
|
||||
Before: cmder.ReloadConfigFunc,
|
||||
Action: func(c *cli.Context) error {
|
||||
if config.Config.ActiveUser() == nil {
|
||||
fmt.Println("未登录账号")
|
||||
return nil
|
||||
}
|
||||
blockSize := int64(c.Int("bs") * 1024)
|
||||
RunSync(blockSize)
|
||||
return nil
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "log",
|
||||
Usage: "开启log输出",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "bs",
|
||||
Usage: "block size,上传分片大小,单位KB。推荐值:1024 ~ 10240",
|
||||
Value: 10240,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func RunSync(uploadBlockSize int64) {
|
||||
activeUser := GetActiveUser()
|
||||
panClient := activeUser.PanClient()
|
||||
|
||||
// pan token expired checker
|
||||
go func() {
|
||||
for {
|
||||
time.Sleep(time.Duration(1) * time.Minute)
|
||||
if RefreshTokenInNeed(activeUser) {
|
||||
logger.Verboseln("update access token for sync task")
|
||||
panClient.UpdateToken(activeUser.WebToken)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
syncFolderRootPath := config.GetSyncDriveDir()
|
||||
if b, e := utils.PathExists(syncFolderRootPath); e == nil {
|
||||
if !b {
|
||||
os.MkdirAll(syncFolderRootPath, 0600)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("启动同步备份进程")
|
||||
syncMgr := syncdrive.NewSyncTaskManager(activeUser.DriveList.GetFileDriveId(), panClient, syncFolderRootPath)
|
||||
if _, e := syncMgr.Start(); e != nil {
|
||||
fmt.Println("启动任务失败:", e)
|
||||
return
|
||||
}
|
||||
c := ""
|
||||
for strings.ToLower(c) != "y" {
|
||||
fmt.Print("本命令不会退出,如需要结束同步备份进程请输入y,然后按Enter键进行停止:")
|
||||
fmt.Scan(&c)
|
||||
}
|
||||
fmt.Println("正在停止同步备份任务,请稍等...")
|
||||
syncMgr.Stop()
|
||||
}
|
@ -308,10 +308,16 @@ func GetConfigDir() string {
|
||||
return configDir
|
||||
}
|
||||
|
||||
// GetPluginDir 获取插件文件夹路径
|
||||
func GetPluginDir() string {
|
||||
return strings.TrimSuffix(GetConfigDir(), "/") + "/plugin"
|
||||
}
|
||||
|
||||
// GetSyncDriveDir 获取同步备份的文件夹路径
|
||||
func GetSyncDriveDir() string {
|
||||
return strings.TrimSuffix(GetConfigDir(), "/") + "/sync_drive"
|
||||
}
|
||||
|
||||
func (c *PanConfig) ActiveUser() *PanUser {
|
||||
if c.activeUser == nil {
|
||||
if c.UserList == nil {
|
||||
|
@ -235,10 +235,10 @@ func (f *FileActionTaskManager) doFileDiffRoutine(panFiles PanFileList, localFil
|
||||
localFilesNeedToCheck, panFilesNeedToCheck := localFilesSet.Intersection(panFilesSet)
|
||||
|
||||
// download file from pan drive
|
||||
if f.task.Mode == DownloadOnly || f.task.Mode == SyncTwoWay {
|
||||
if panFilesNeedToDownload != nil {
|
||||
for _, file := range panFilesNeedToDownload {
|
||||
if file.ScanStatus == ScanStatusNormal { // 下载文件
|
||||
if panFilesNeedToDownload != nil {
|
||||
for _, file := range panFilesNeedToDownload {
|
||||
if file.ScanStatus == ScanStatusNormal { // 下载文件
|
||||
if f.task.Mode == DownloadOnly || f.task.Mode == SyncTwoWay {
|
||||
if file.IsFolder() {
|
||||
if panFolderQueue != nil {
|
||||
panFolderQueue.PushUnique(file)
|
||||
@ -259,7 +259,9 @@ func (f *FileActionTaskManager) doFileDiffRoutine(panFiles PanFileList, localFil
|
||||
},
|
||||
}
|
||||
f.addToSyncDb(fileActionTask)
|
||||
} else if file.ScanStatus == ScanStatusDiscard { // 删除对应本地文件(文件夹)
|
||||
}
|
||||
} else if file.ScanStatus == ScanStatusDiscard { // 删除对应本地文件(文件夹)
|
||||
if f.task.Mode == DownloadOnly || f.task.Mode == SyncTwoWay {
|
||||
fileActionTask := &FileActionTask{
|
||||
syncItem: &SyncFileItem{
|
||||
Action: SyncFileActionDeleteLocal,
|
||||
@ -274,16 +276,19 @@ func (f *FileActionTaskManager) doFileDiffRoutine(panFiles PanFileList, localFil
|
||||
},
|
||||
}
|
||||
f.addToSyncDb(fileActionTask)
|
||||
} else if f.task.Mode == UploadOnly {
|
||||
// 删除无用记录
|
||||
f.task.panFileDb.Delete(file.Path)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// upload file to pan drive
|
||||
if f.task.Mode == UploadOnly || f.task.Mode == SyncTwoWay {
|
||||
if localFilesNeedToUpload != nil {
|
||||
for _, file := range localFilesNeedToUpload {
|
||||
if file.ScanStatus == ScanStatusNormal { // 上传文件到云盘
|
||||
if localFilesNeedToUpload != nil {
|
||||
for _, file := range localFilesNeedToUpload {
|
||||
if file.ScanStatus == ScanStatusNormal { // 上传文件到云盘
|
||||
if f.task.Mode == UploadOnly || f.task.Mode == SyncTwoWay {
|
||||
if file.IsFolder() {
|
||||
if localFolderQueue != nil {
|
||||
localFolderQueue.PushUnique(file)
|
||||
@ -304,7 +309,9 @@ func (f *FileActionTaskManager) doFileDiffRoutine(panFiles PanFileList, localFil
|
||||
},
|
||||
}
|
||||
f.addToSyncDb(fileActionTask)
|
||||
} else if file.ScanStatus == ScanStatusDiscard { // 删除对应云盘文件(文件夹)
|
||||
}
|
||||
} else if file.ScanStatus == ScanStatusDiscard { // 删除对应云盘文件(文件夹)
|
||||
if f.task.Mode == UploadOnly || f.task.Mode == SyncTwoWay {
|
||||
fileActionTask := &FileActionTask{
|
||||
syncItem: &SyncFileItem{
|
||||
Action: SyncFileActionDeletePan,
|
||||
@ -319,6 +326,9 @@ func (f *FileActionTaskManager) doFileDiffRoutine(panFiles PanFileList, localFil
|
||||
},
|
||||
}
|
||||
f.addToSyncDb(fileActionTask)
|
||||
} else if f.task.Mode == DownloadOnly {
|
||||
// 删除无用记录
|
||||
f.task.localFileDb.Delete(file.Path)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -355,6 +365,9 @@ func (f *FileActionTaskManager) doFileDiffRoutine(panFiles PanFileList, localFil
|
||||
},
|
||||
}
|
||||
f.addToSyncDb(deletePanFile)
|
||||
} else if f.task.Mode == DownloadOnly {
|
||||
// 删除无用记录
|
||||
f.task.localFileDb.Delete(localFile.Path)
|
||||
}
|
||||
continue
|
||||
}
|
||||
@ -375,6 +388,9 @@ func (f *FileActionTaskManager) doFileDiffRoutine(panFiles PanFileList, localFil
|
||||
},
|
||||
}
|
||||
f.addToSyncDb(deletePanFile)
|
||||
} else if f.task.Mode == UploadOnly {
|
||||
// 删除无用记录
|
||||
f.task.panFileDb.Delete(panFile.Path)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ type (
|
||||
// Id 任务ID
|
||||
Id string `json:"id"`
|
||||
// DriveId 网盘ID,目前支持文件网盘
|
||||
DriveId string `json:"driveId"`
|
||||
DriveId string `json:"-"`
|
||||
// LocalFolderPath 本地目录
|
||||
LocalFolderPath string `json:"localFolderPath"`
|
||||
// PanFolderPath 云盘目录
|
||||
@ -66,12 +66,12 @@ func (t *SyncTask) NameLabel() string {
|
||||
func (t *SyncTask) String() string {
|
||||
builder := &strings.Builder{}
|
||||
builder.WriteString("任务: " + t.NameLabel() + "\n")
|
||||
mode := "双向同步"
|
||||
mode := "双向备份"
|
||||
if t.Mode == UploadOnly {
|
||||
mode = "只上传"
|
||||
mode = "备份本地文件(只上传)"
|
||||
}
|
||||
if t.Mode == UploadOnly {
|
||||
mode = "只下载"
|
||||
if t.Mode == DownloadOnly {
|
||||
mode = "备份云盘文件(只下载)"
|
||||
}
|
||||
builder.WriteString("同步模式: " + mode + "\n")
|
||||
builder.WriteString("本地目录: " + t.LocalFolderPath + "\n")
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"github.com/tickstep/library-go/logger"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
@ -63,9 +64,9 @@ func (m *SyncTaskManager) parseConfigFile() error {
|
||||
m.syncDriveConfig = r
|
||||
|
||||
if b, _ := utils.PathExists(configFilePath); b != true {
|
||||
text := utils.ObjectToJsonStr(r, true)
|
||||
ioutil.WriteFile(configFilePath, []byte(text), 0600)
|
||||
return nil
|
||||
//text := utils.ObjectToJsonStr(r, true)
|
||||
//ioutil.WriteFile(configFilePath, []byte(text), 0600)
|
||||
return fmt.Errorf("备份配置文件不存在")
|
||||
}
|
||||
data, e := ioutil.ReadFile(configFilePath)
|
||||
if e != nil {
|
||||
@ -109,11 +110,10 @@ func (m *SyncTaskManager) Start() (bool, error) {
|
||||
}
|
||||
fmt.Println("\n启动同步任务")
|
||||
fmt.Println(task)
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
}
|
||||
// save config file
|
||||
ioutil.WriteFile(m.configFilePath(), []byte(utils.ObjectToJsonStr(m.syncDriveConfig, true)), 0600)
|
||||
|
||||
// TODO: refresh panClient token to keep access token alive
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user