diff --git a/fs/sync/rc.go b/fs/sync/rc.go new file mode 100644 index 000000000..080ac8365 --- /dev/null +++ b/fs/sync/rc.go @@ -0,0 +1,57 @@ +package sync + +import ( + "github.com/ncw/rclone/fs/rc" +) + +func init() { + for _, name := range []string{"sync", "copy", "move"} { + name := name + moveHelp := "" + if name == "move" { + moveHelp = "- deleteEmptySrcDirs - delete empty src directories if set\n" + } + rc.Add(rc.Call{ + Path: "sync/" + name, + AuthRequired: true, + Fn: func(in rc.Params) (rc.Params, error) { + return rcSyncCopyMove(in, name) + }, + Title: name + " a directory from source remote to destination remote", + Help: `This takes the following parameters + +- srcFs - a remote name string eg "drive:src" for the source +- dstFs - a remote name string eg "drive:dst" for the destination +` + moveHelp + ` +This returns +- jobid - ID of async job to query with job/status + +See the [` + name + ` command](/commands/rclone_` + name + `/) command for more information on the above.`, + }) + } +} + +// Sync/Copy/Move a file +func rcSyncCopyMove(in rc.Params, name string) (out rc.Params, err error) { + srcFs, err := rc.GetFsNamed(in, "srcFs") + if err != nil { + return nil, err + } + dstFs, err := rc.GetFsNamed(in, "dstFs") + if err != nil { + return nil, err + } + switch name { + case "sync": + return nil, Sync(dstFs, srcFs) + case "copy": + return nil, CopyDir(dstFs, srcFs) + case "move": + deleteEmptySrcDirs, err := in.GetBool("deleteEmptySrcDirs") + if rc.NotErrParamNotFound(err) { + return nil, err + } + return nil, MoveDir(dstFs, srcFs, deleteEmptySrcDirs) + } + panic("unknown rcSyncCopyMove type") +} diff --git a/fs/sync/rc_test.go b/fs/sync/rc_test.go new file mode 100644 index 000000000..346796e05 --- /dev/null +++ b/fs/sync/rc_test.go @@ -0,0 +1,97 @@ +package sync + +import ( + "testing" + + "github.com/ncw/rclone/fs/rc" + "github.com/ncw/rclone/fstest" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func rcNewRun(t *testing.T, method string) (*fstest.Run, *rc.Call) { + if *fstest.RemoteName != "" { + t.Skip("Skipping test on non local remote") + } + r := fstest.NewRun(t) + call := rc.Calls.Get(method) + assert.NotNil(t, call) + rc.PutCachedFs(r.LocalName, r.Flocal) + rc.PutCachedFs(r.FremoteName, r.Fremote) + return r, call +} + +// sync/copy: copy a directory from source remote to destination remote +func TestRcCopy(t *testing.T) { + r, call := rcNewRun(t, "sync/copy") + defer r.Finalise() + r.Mkdir(r.Fremote) + + file1 := r.WriteBoth("file1", "file1 contents", t1) + file2 := r.WriteFile("subdir/file2", "file2 contents", t2) + file3 := r.WriteObject("subdir/subsubdir/file3", "file3 contents", t3) + + fstest.CheckItems(t, r.Flocal, file1, file2) + fstest.CheckItems(t, r.Fremote, file1, file3) + + in := rc.Params{ + "srcFs": r.LocalName, + "dstFs": r.FremoteName, + } + out, err := call.Fn(in) + require.NoError(t, err) + assert.Equal(t, rc.Params(nil), out) + + fstest.CheckItems(t, r.Flocal, file1, file2) + fstest.CheckItems(t, r.Fremote, file1, file2, file3) +} + +// sync/move: move a directory from source remote to destination remote +func TestRcMove(t *testing.T) { + r, call := rcNewRun(t, "sync/move") + defer r.Finalise() + r.Mkdir(r.Fremote) + + file1 := r.WriteBoth("file1", "file1 contents", t1) + file2 := r.WriteFile("subdir/file2", "file2 contents", t2) + file3 := r.WriteObject("subdir/subsubdir/file3", "file3 contents", t3) + + fstest.CheckItems(t, r.Flocal, file1, file2) + fstest.CheckItems(t, r.Fremote, file1, file3) + + in := rc.Params{ + "srcFs": r.LocalName, + "dstFs": r.FremoteName, + } + out, err := call.Fn(in) + require.NoError(t, err) + assert.Equal(t, rc.Params(nil), out) + + fstest.CheckItems(t, r.Flocal) + fstest.CheckItems(t, r.Fremote, file1, file2, file3) +} + +// sync/sync: sync a directory from source remote to destination remote +func TestRcSync(t *testing.T) { + r, call := rcNewRun(t, "sync/sync") + defer r.Finalise() + r.Mkdir(r.Fremote) + + file1 := r.WriteBoth("file1", "file1 contents", t1) + file2 := r.WriteFile("subdir/file2", "file2 contents", t2) + file3 := r.WriteObject("subdir/subsubdir/file3", "file3 contents", t3) + + fstest.CheckItems(t, r.Flocal, file1, file2) + fstest.CheckItems(t, r.Fremote, file1, file3) + + in := rc.Params{ + "srcFs": r.LocalName, + "dstFs": r.FremoteName, + } + out, err := call.Fn(in) + require.NoError(t, err) + assert.Equal(t, rc.Params(nil), out) + + fstest.CheckItems(t, r.Flocal, file1, file2) + fstest.CheckItems(t, r.Fremote, file1, file2) +}