mirror of
https://github.com/rclone/rclone.git
synced 2024-12-28 23:44:06 +08:00
bbf9b1b3d2
Before this change, bisync supported `--backup-dir` only when `Path1` and `Path2` were different paths on the same remote. With this change, bisync introduces new `--backup-dir1` and `--backup-dir2` flags to support separate backup-dirs for `Path1` and `Path2`. `--backup-dir1` and `--backup-dir2` can use different remotes from each other, but `--backup-dir1` must use the same remote as `Path1`, and `--backup-dir2` must use the same remote as `Path2`. Each backup directory must not overlap its respective bisync Path without being excluded by a filter rule. The standard `--backup-dir` will also work, if both paths use the same remote (but note that deleted files from both paths would be mixed together in the same dir). If either `--backup-dir1` and `--backup-dir2` are set, they will override `--backup-dir`.
111 lines
2.7 KiB
Go
111 lines
2.7 KiB
Go
package bisync
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"log"
|
|
|
|
"github.com/rclone/rclone/cmd/bisync/bilib"
|
|
"github.com/rclone/rclone/fs"
|
|
"github.com/rclone/rclone/fs/rc"
|
|
)
|
|
|
|
func init() {
|
|
rc.Add(rc.Call{
|
|
Path: "sync/bisync",
|
|
AuthRequired: true,
|
|
Fn: rcBisync,
|
|
Title: shortHelp,
|
|
Help: rcHelp,
|
|
})
|
|
}
|
|
|
|
func rcBisync(ctx context.Context, in rc.Params) (out rc.Params, err error) {
|
|
opt := &Options{}
|
|
octx, ci := fs.AddConfig(ctx)
|
|
|
|
if dryRun, err := in.GetBool("dryRun"); err == nil {
|
|
ci.DryRun = dryRun
|
|
opt.DryRun = dryRun
|
|
} else if rc.NotErrParamNotFound(err) {
|
|
return nil, err
|
|
}
|
|
|
|
if maxDelete, err := in.GetInt64("maxDelete"); err == nil {
|
|
if maxDelete < 0 || maxDelete > 100 {
|
|
return nil, rc.NewErrParamInvalid(errors.New("maxDelete must be a percentage between 0 and 100"))
|
|
}
|
|
opt.MaxDelete = int(maxDelete)
|
|
} else if rc.NotErrParamNotFound(err) {
|
|
return nil, err
|
|
}
|
|
|
|
if opt.Resync, err = in.GetBool("resync"); rc.NotErrParamNotFound(err) {
|
|
return
|
|
}
|
|
if opt.CheckAccess, err = in.GetBool("checkAccess"); rc.NotErrParamNotFound(err) {
|
|
return
|
|
}
|
|
if opt.Force, err = in.GetBool("force"); rc.NotErrParamNotFound(err) {
|
|
return
|
|
}
|
|
if opt.CreateEmptySrcDirs, err = in.GetBool("createEmptySrcDirs"); rc.NotErrParamNotFound(err) {
|
|
return
|
|
}
|
|
if opt.RemoveEmptyDirs, err = in.GetBool("removeEmptyDirs"); rc.NotErrParamNotFound(err) {
|
|
return
|
|
}
|
|
if opt.NoCleanup, err = in.GetBool("noCleanup"); rc.NotErrParamNotFound(err) {
|
|
return
|
|
}
|
|
if opt.IgnoreListingChecksum, err = in.GetBool("ignoreListingChecksum"); rc.NotErrParamNotFound(err) {
|
|
return
|
|
}
|
|
if opt.Resilient, err = in.GetBool("resilient"); rc.NotErrParamNotFound(err) {
|
|
return
|
|
}
|
|
|
|
if opt.CheckFilename, err = in.GetString("checkFilename"); rc.NotErrParamNotFound(err) {
|
|
return
|
|
}
|
|
if opt.FiltersFile, err = in.GetString("filtersFile"); rc.NotErrParamNotFound(err) {
|
|
return
|
|
}
|
|
if opt.Workdir, err = in.GetString("workdir"); rc.NotErrParamNotFound(err) {
|
|
return
|
|
}
|
|
if opt.BackupDir1, err = in.GetString("backupdir1"); rc.NotErrParamNotFound(err) {
|
|
return
|
|
}
|
|
if opt.BackupDir2, err = in.GetString("backupdir2"); rc.NotErrParamNotFound(err) {
|
|
return
|
|
}
|
|
|
|
checkSync, err := in.GetString("checkSync")
|
|
if rc.NotErrParamNotFound(err) {
|
|
return nil, err
|
|
}
|
|
if checkSync == "" {
|
|
checkSync = "true"
|
|
}
|
|
if err := opt.CheckSync.Set(checkSync); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
fs1, err := rc.GetFsNamed(octx, in, "path1")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
fs2, err := rc.GetFsNamed(octx, in, "path2")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
output := bilib.CaptureOutput(func() {
|
|
err = Bisync(octx, fs1, fs2, opt)
|
|
})
|
|
_, _ = log.Writer().Write(output)
|
|
return rc.Params{"output": string(output)}, err
|
|
}
|