2018-10-26 15:51:28 +02:00
package operations
import (
2019-06-17 10:34:30 +02:00
"context"
2018-10-26 15:51:28 +02:00
"strings"
"github.com/pkg/errors"
2019-07-28 19:47:38 +02:00
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/rc"
2018-10-26 15:51:28 +02:00
)
func init ( ) {
rc . Add ( rc . Call {
Path : "operations/list" ,
AuthRequired : true ,
Fn : rcList ,
Title : "List the given remote and path in JSON format" ,
Help : ` This takes the following parameters
- fs - a remote name string eg "drive:"
- remote - a path within that remote eg "dir"
- opt - a dictionary of options to control the listing ( optional )
- recurse - If set recurse directories
- noModTime - If set return modification time
- showEncrypted - If set show decrypted names
- showOrigIDs - If set show the IDs for each item if known
- showHash - If set return a dictionary of hashes
The result is
- list
- This is an array of objects as described in the lsjson command
2019-06-07 18:28:15 +02:00
See the [ lsjson command ] ( / commands / rclone_lsjson / ) for more information on the above and examples .
2018-10-26 15:51:28 +02:00
` ,
} )
}
// List the directory
2019-06-17 10:34:30 +02:00
func rcList ( ctx context . Context , in rc . Params ) ( out rc . Params , err error ) {
2018-10-26 15:51:28 +02:00
f , remote , err := rc . GetFsAndRemote ( in )
if err != nil {
return nil , err
}
var opt ListJSONOpt
err = in . GetStruct ( "opt" , & opt )
if rc . NotErrParamNotFound ( err ) {
return nil , err
}
var list = [ ] * ListJSONItem { }
2019-06-17 10:34:30 +02:00
err = ListJSON ( ctx , f , remote , & opt , func ( item * ListJSONItem ) error {
2018-10-26 15:51:28 +02:00
list = append ( list , item )
return nil
} )
if err != nil {
return nil , err
}
out = make ( rc . Params )
out [ "list" ] = list
return out , nil
}
func init ( ) {
rc . Add ( rc . Call {
Path : "operations/about" ,
AuthRequired : true ,
Fn : rcAbout ,
Title : "Return the space used on the remote" ,
Help : ` This takes the following parameters
- fs - a remote name string eg "drive:"
The result is as returned from rclone about -- json
2019-06-08 10:19:07 +02:00
See the [ about command ] ( / commands / rclone_size / ) command for more information on the above .
2018-10-26 15:51:28 +02:00
` ,
} )
}
// About the remote
2019-06-17 10:34:30 +02:00
func rcAbout ( ctx context . Context , in rc . Params ) ( out rc . Params , err error ) {
2018-10-26 15:51:28 +02:00
f , err := rc . GetFs ( in )
if err != nil {
return nil , err
}
doAbout := f . Features ( ) . About
if doAbout == nil {
return nil , errors . Errorf ( "%v doesn't support about" , f )
}
2019-06-17 10:34:30 +02:00
u , err := doAbout ( ctx )
2018-10-26 15:51:28 +02:00
if err != nil {
return nil , errors . Wrap ( err , "about call failed" )
}
err = rc . Reshape ( & out , u )
if err != nil {
return nil , errors . Wrap ( err , "about Reshape failed" )
}
return out , nil
}
func init ( ) {
for _ , copy := range [ ] bool { false , true } {
copy := copy
name := "Move"
if copy {
name = "Copy"
}
rc . Add ( rc . Call {
Path : "operations/" + strings . ToLower ( name ) + "file" ,
AuthRequired : true ,
2019-06-17 10:34:30 +02:00
Fn : func ( ctx context . Context , in rc . Params ) ( rc . Params , error ) {
return rcMoveOrCopyFile ( ctx , in , copy )
2018-10-26 15:51:28 +02:00
} ,
Title : name + " a file from source remote to destination remote" ,
Help : ` This takes the following parameters
- srcFs - a remote name string eg "drive:" for the source
- srcRemote - a path within that remote eg "file.txt" for the source
- dstFs - a remote name string eg "drive2:" for the destination
- dstRemote - a path within that remote eg "file2.txt" for the destination
` ,
} )
}
}
// Copy a file
2019-06-17 10:34:30 +02:00
func rcMoveOrCopyFile ( ctx context . Context , in rc . Params , cp bool ) ( out rc . Params , err error ) {
2018-10-26 15:51:28 +02:00
srcFs , srcRemote , err := rc . GetFsAndRemoteNamed ( in , "srcFs" , "srcRemote" )
if err != nil {
return nil , err
}
dstFs , dstRemote , err := rc . GetFsAndRemoteNamed ( in , "dstFs" , "dstRemote" )
if err != nil {
return nil , err
}
2019-06-17 10:34:30 +02:00
return nil , moveOrCopyFile ( ctx , dstFs , srcFs , dstRemote , srcRemote , cp )
2018-10-26 15:51:28 +02:00
}
func init ( ) {
for _ , op := range [ ] struct {
name string
title string
help string
noRemote bool
} {
{ name : "mkdir" , title : "Make a destination directory or container" } ,
{ name : "rmdir" , title : "Remove an empty directory or container" } ,
{ name : "purge" , title : "Remove a directory or container and all of its contents" } ,
{ name : "rmdirs" , title : "Remove all the empty directories in the path" , help : "- leaveRoot - boolean, set to true not to delete the root\n" } ,
{ name : "delete" , title : "Remove files in the path" , noRemote : true } ,
{ name : "deletefile" , title : "Remove the single file pointed to" } ,
2019-09-03 18:25:19 +02:00
{ name : "copyurl" , title : "Copy the URL to the object" , help : "- url - string, URL to read from\n - autoFilename - boolean, set to true to retrieve destination file name from url" } ,
2018-10-26 15:51:28 +02:00
{ name : "cleanup" , title : "Remove trashed files in the remote or path" , noRemote : true } ,
} {
op := op
remote := "- remote - a path within that remote eg \"dir\"\n"
if op . noRemote {
remote = ""
}
rc . Add ( rc . Call {
Path : "operations/" + op . name ,
AuthRequired : true ,
2019-06-17 10:34:30 +02:00
Fn : func ( ctx context . Context , in rc . Params ) ( rc . Params , error ) {
return rcSingleCommand ( ctx , in , op . name , op . noRemote )
2018-10-26 15:51:28 +02:00
} ,
Title : op . title ,
Help : ` This takes the following parameters
- fs - a remote name string eg "drive:"
` + remote + op.help + `
See the [ ` + op.name + ` command ] ( / commands / rclone_ ` + op.name + ` / ) command for more information on the above .
` ,
} )
}
}
2019-03-11 17:59:27 +01:00
// Run a single command, eg Mkdir
2019-06-17 10:34:30 +02:00
func rcSingleCommand ( ctx context . Context , in rc . Params , name string , noRemote bool ) ( out rc . Params , err error ) {
2018-10-26 15:51:28 +02:00
var (
f fs . Fs
remote string
)
if noRemote {
f , err = rc . GetFs ( in )
} else {
f , remote , err = rc . GetFsAndRemote ( in )
}
if err != nil {
return nil , err
}
switch name {
case "mkdir" :
2019-06-17 10:34:30 +02:00
return nil , Mkdir ( ctx , f , remote )
2018-10-26 15:51:28 +02:00
case "rmdir" :
2019-06-17 10:34:30 +02:00
return nil , Rmdir ( ctx , f , remote )
2018-10-26 15:51:28 +02:00
case "purge" :
2019-06-17 10:34:30 +02:00
return nil , Purge ( ctx , f , remote )
2018-10-26 15:51:28 +02:00
case "rmdirs" :
leaveRoot , err := in . GetBool ( "leaveRoot" )
if rc . NotErrParamNotFound ( err ) {
return nil , err
}
2019-06-17 10:34:30 +02:00
return nil , Rmdirs ( ctx , f , remote , leaveRoot )
2018-10-26 15:51:28 +02:00
case "delete" :
2019-06-17 10:34:30 +02:00
return nil , Delete ( ctx , f )
2018-10-26 15:51:28 +02:00
case "deletefile" :
2019-06-17 10:34:30 +02:00
o , err := f . NewObject ( ctx , remote )
2018-10-26 15:51:28 +02:00
if err != nil {
return nil , err
}
2019-06-17 10:34:30 +02:00
return nil , DeleteFile ( ctx , o )
2018-10-26 15:51:28 +02:00
case "copyurl" :
url , err := in . GetString ( "url" )
if err != nil {
return nil , err
}
2019-09-03 18:25:19 +02:00
autoFilename , _ := in . GetBool ( "autoFilename" )
2020-04-19 13:40:17 +02:00
noClobber , _ := in . GetBool ( "noClobber" )
2019-09-03 18:25:19 +02:00
2020-04-19 13:40:17 +02:00
_ , err = CopyURL ( ctx , f , remote , url , autoFilename , noClobber )
2018-10-26 15:51:28 +02:00
return nil , err
case "cleanup" :
2019-06-17 10:34:30 +02:00
return nil , CleanUp ( ctx , f )
2018-10-26 15:51:28 +02:00
}
panic ( "unknown rcSingleCommand type" )
}
func init ( ) {
rc . Add ( rc . Call {
Path : "operations/size" ,
AuthRequired : true ,
Fn : rcSize ,
Title : "Count the number of bytes and files in remote" ,
Help : ` This takes the following parameters
- fs - a remote name string eg "drive:path/to/dir"
Returns
- count - number of files
- bytes - number of bytes in those files
See the [ size command ] ( / commands / rclone_size / ) command for more information on the above .
` ,
} )
}
2019-03-11 17:59:27 +01:00
// Size a directory
2019-06-17 10:34:30 +02:00
func rcSize ( ctx context . Context , in rc . Params ) ( out rc . Params , err error ) {
2018-10-26 15:51:28 +02:00
f , err := rc . GetFs ( in )
if err != nil {
return nil , err
}
2019-06-17 10:34:30 +02:00
count , bytes , err := Count ( ctx , f )
2018-10-26 15:51:28 +02:00
if err != nil {
return nil , err
}
out = make ( rc . Params )
out [ "count" ] = count
out [ "bytes" ] = bytes
return out , nil
}
2019-03-11 17:59:27 +01:00
func init ( ) {
rc . Add ( rc . Call {
Path : "operations/publiclink" ,
AuthRequired : true ,
Fn : rcPublicLink ,
Title : "Create or retrieve a public link to the given file or folder." ,
Help : ` This takes the following parameters
- fs - a remote name string eg "drive:"
- remote - a path within that remote eg "dir"
Returns
- url - URL of the resource
See the [ link command ] ( / commands / rclone_link / ) command for more information on the above .
` ,
} )
}
// Make a public link
2019-06-17 10:34:30 +02:00
func rcPublicLink ( ctx context . Context , in rc . Params ) ( out rc . Params , err error ) {
2019-03-11 17:59:27 +01:00
f , remote , err := rc . GetFsAndRemote ( in )
if err != nil {
return nil , err
}
2019-06-17 10:34:30 +02:00
url , err := PublicLink ( ctx , f , remote )
2019-03-11 17:59:27 +01:00
if err != nil {
return nil , err
}
out = make ( rc . Params )
out [ "url" ] = url
return out , nil
}
2019-06-08 10:19:07 +02:00
func init ( ) {
rc . Add ( rc . Call {
Path : "operations/fsinfo" ,
Fn : rcFsInfo ,
Title : "Return information about the remote" ,
Help : ` This takes the following parameters
- fs - a remote name string eg "drive:"
This returns info about the remote passed in ;
` + " ` ` ` " + `
{
// optional features and whether they are available or not
"Features" : {
"About" : true ,
"BucketBased" : false ,
"CanHaveEmptyDirectories" : true ,
"CaseInsensitive" : false ,
"ChangeNotify" : false ,
"CleanUp" : false ,
"Copy" : false ,
"DirCacheFlush" : false ,
"DirMove" : true ,
"DuplicateFiles" : false ,
"GetTier" : false ,
"ListR" : false ,
"MergeDirs" : false ,
"Move" : true ,
"OpenWriterAt" : true ,
"PublicLink" : false ,
"Purge" : true ,
"PutStream" : true ,
"PutUnchecked" : false ,
"ReadMimeType" : false ,
"ServerSideAcrossConfigs" : false ,
"SetTier" : false ,
"SetWrapper" : false ,
"UnWrap" : false ,
"WrapFs" : false ,
"WriteMimeType" : false
} ,
// Names of hashes available
"Hashes" : [
"MD5" ,
"SHA-1" ,
"DropboxHash" ,
"QuickXorHash"
] ,
"Name" : "local" , // Name as created
"Precision" : 1 , // Precision of timestamps in ns
"Root" : "/" , // Path as created
"String" : "Local file system at /" // how the remote will appear in logs
}
` + " ` ` ` " + `
This command does not have a command line equivalent so use this instead :
rclone rc -- loopback operations / fsinfo fs = remote :
` ,
} )
}
// Fsinfo the remote
2019-06-17 10:34:30 +02:00
func rcFsInfo ( ctx context . Context , in rc . Params ) ( out rc . Params , err error ) {
2019-06-08 10:19:07 +02:00
f , err := rc . GetFs ( in )
if err != nil {
return nil , err
}
info := GetFsInfo ( f )
err = rc . Reshape ( & out , info )
if err != nil {
return nil , errors . Wrap ( err , "fsinfo Reshape failed" )
}
return out , nil
}