github.com/xhghs/rclone@v1.51.1-0.20200430155106-e186a28cced8/fs/operations/rc.go (about) 1 package operations 2 3 import ( 4 "context" 5 "strings" 6 7 "github.com/pkg/errors" 8 "github.com/rclone/rclone/fs" 9 "github.com/rclone/rclone/fs/rc" 10 ) 11 12 func init() { 13 rc.Add(rc.Call{ 14 Path: "operations/list", 15 AuthRequired: true, 16 Fn: rcList, 17 Title: "List the given remote and path in JSON format", 18 Help: `This takes the following parameters 19 20 - fs - a remote name string eg "drive:" 21 - remote - a path within that remote eg "dir" 22 - opt - a dictionary of options to control the listing (optional) 23 - recurse - If set recurse directories 24 - noModTime - If set return modification time 25 - showEncrypted - If set show decrypted names 26 - showOrigIDs - If set show the IDs for each item if known 27 - showHash - If set return a dictionary of hashes 28 29 The result is 30 31 - list 32 - This is an array of objects as described in the lsjson command 33 34 See the [lsjson command](/commands/rclone_lsjson/) for more information on the above and examples. 35 `, 36 }) 37 } 38 39 // List the directory 40 func rcList(ctx context.Context, in rc.Params) (out rc.Params, err error) { 41 f, remote, err := rc.GetFsAndRemote(in) 42 if err != nil { 43 return nil, err 44 } 45 var opt ListJSONOpt 46 err = in.GetStruct("opt", &opt) 47 if rc.NotErrParamNotFound(err) { 48 return nil, err 49 } 50 var list = []*ListJSONItem{} 51 err = ListJSON(ctx, f, remote, &opt, func(item *ListJSONItem) error { 52 list = append(list, item) 53 return nil 54 }) 55 if err != nil { 56 return nil, err 57 } 58 out = make(rc.Params) 59 out["list"] = list 60 return out, nil 61 } 62 63 func init() { 64 rc.Add(rc.Call{ 65 Path: "operations/about", 66 AuthRequired: true, 67 Fn: rcAbout, 68 Title: "Return the space used on the remote", 69 Help: `This takes the following parameters 70 71 - fs - a remote name string eg "drive:" 72 73 The result is as returned from rclone about --json 74 75 See the [about command](/commands/rclone_size/) command for more information on the above. 76 `, 77 }) 78 } 79 80 // About the remote 81 func rcAbout(ctx context.Context, in rc.Params) (out rc.Params, err error) { 82 f, err := rc.GetFs(in) 83 if err != nil { 84 return nil, err 85 } 86 doAbout := f.Features().About 87 if doAbout == nil { 88 return nil, errors.Errorf("%v doesn't support about", f) 89 } 90 u, err := doAbout(ctx) 91 if err != nil { 92 return nil, errors.Wrap(err, "about call failed") 93 } 94 err = rc.Reshape(&out, u) 95 if err != nil { 96 return nil, errors.Wrap(err, "about Reshape failed") 97 } 98 return out, nil 99 } 100 101 func init() { 102 for _, copy := range []bool{false, true} { 103 copy := copy 104 name := "Move" 105 if copy { 106 name = "Copy" 107 } 108 rc.Add(rc.Call{ 109 Path: "operations/" + strings.ToLower(name) + "file", 110 AuthRequired: true, 111 Fn: func(ctx context.Context, in rc.Params) (rc.Params, error) { 112 return rcMoveOrCopyFile(ctx, in, copy) 113 }, 114 Title: name + " a file from source remote to destination remote", 115 Help: `This takes the following parameters 116 117 - srcFs - a remote name string eg "drive:" for the source 118 - srcRemote - a path within that remote eg "file.txt" for the source 119 - dstFs - a remote name string eg "drive2:" for the destination 120 - dstRemote - a path within that remote eg "file2.txt" for the destination 121 `, 122 }) 123 } 124 } 125 126 // Copy a file 127 func rcMoveOrCopyFile(ctx context.Context, in rc.Params, cp bool) (out rc.Params, err error) { 128 srcFs, srcRemote, err := rc.GetFsAndRemoteNamed(in, "srcFs", "srcRemote") 129 if err != nil { 130 return nil, err 131 } 132 dstFs, dstRemote, err := rc.GetFsAndRemoteNamed(in, "dstFs", "dstRemote") 133 if err != nil { 134 return nil, err 135 } 136 return nil, moveOrCopyFile(ctx, dstFs, srcFs, dstRemote, srcRemote, cp) 137 } 138 139 func init() { 140 for _, op := range []struct { 141 name string 142 title string 143 help string 144 noRemote bool 145 }{ 146 {name: "mkdir", title: "Make a destination directory or container"}, 147 {name: "rmdir", title: "Remove an empty directory or container"}, 148 {name: "purge", title: "Remove a directory or container and all of its contents"}, 149 {name: "rmdirs", title: "Remove all the empty directories in the path", help: "- leaveRoot - boolean, set to true not to delete the root\n"}, 150 {name: "delete", title: "Remove files in the path", noRemote: true}, 151 {name: "deletefile", title: "Remove the single file pointed to"}, 152 {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"}, 153 {name: "cleanup", title: "Remove trashed files in the remote or path", noRemote: true}, 154 } { 155 op := op 156 remote := "- remote - a path within that remote eg \"dir\"\n" 157 if op.noRemote { 158 remote = "" 159 } 160 rc.Add(rc.Call{ 161 Path: "operations/" + op.name, 162 AuthRequired: true, 163 Fn: func(ctx context.Context, in rc.Params) (rc.Params, error) { 164 return rcSingleCommand(ctx, in, op.name, op.noRemote) 165 }, 166 Title: op.title, 167 Help: `This takes the following parameters 168 169 - fs - a remote name string eg "drive:" 170 ` + remote + op.help + ` 171 See the [` + op.name + ` command](/commands/rclone_` + op.name + `/) command for more information on the above. 172 `, 173 }) 174 } 175 } 176 177 // Run a single command, eg Mkdir 178 func rcSingleCommand(ctx context.Context, in rc.Params, name string, noRemote bool) (out rc.Params, err error) { 179 var ( 180 f fs.Fs 181 remote string 182 ) 183 if noRemote { 184 f, err = rc.GetFs(in) 185 } else { 186 f, remote, err = rc.GetFsAndRemote(in) 187 } 188 if err != nil { 189 return nil, err 190 } 191 switch name { 192 case "mkdir": 193 return nil, Mkdir(ctx, f, remote) 194 case "rmdir": 195 return nil, Rmdir(ctx, f, remote) 196 case "purge": 197 return nil, Purge(ctx, f, remote) 198 case "rmdirs": 199 leaveRoot, err := in.GetBool("leaveRoot") 200 if rc.NotErrParamNotFound(err) { 201 return nil, err 202 } 203 return nil, Rmdirs(ctx, f, remote, leaveRoot) 204 case "delete": 205 return nil, Delete(ctx, f) 206 case "deletefile": 207 o, err := f.NewObject(ctx, remote) 208 if err != nil { 209 return nil, err 210 } 211 return nil, DeleteFile(ctx, o) 212 case "copyurl": 213 url, err := in.GetString("url") 214 if err != nil { 215 return nil, err 216 } 217 autoFilename, _ := in.GetBool("autoFilename") 218 219 _, err = CopyURL(ctx, f, remote, url, autoFilename) 220 return nil, err 221 case "cleanup": 222 return nil, CleanUp(ctx, f) 223 } 224 panic("unknown rcSingleCommand type") 225 } 226 227 func init() { 228 rc.Add(rc.Call{ 229 Path: "operations/size", 230 AuthRequired: true, 231 Fn: rcSize, 232 Title: "Count the number of bytes and files in remote", 233 Help: `This takes the following parameters 234 235 - fs - a remote name string eg "drive:path/to/dir" 236 237 Returns 238 239 - count - number of files 240 - bytes - number of bytes in those files 241 242 See the [size command](/commands/rclone_size/) command for more information on the above. 243 `, 244 }) 245 } 246 247 // Size a directory 248 func rcSize(ctx context.Context, in rc.Params) (out rc.Params, err error) { 249 f, err := rc.GetFs(in) 250 if err != nil { 251 return nil, err 252 } 253 count, bytes, err := Count(ctx, f) 254 if err != nil { 255 return nil, err 256 } 257 out = make(rc.Params) 258 out["count"] = count 259 out["bytes"] = bytes 260 return out, nil 261 } 262 263 func init() { 264 rc.Add(rc.Call{ 265 Path: "operations/publiclink", 266 AuthRequired: true, 267 Fn: rcPublicLink, 268 Title: "Create or retrieve a public link to the given file or folder.", 269 Help: `This takes the following parameters 270 271 - fs - a remote name string eg "drive:" 272 - remote - a path within that remote eg "dir" 273 274 Returns 275 276 - url - URL of the resource 277 278 See the [link command](/commands/rclone_link/) command for more information on the above. 279 `, 280 }) 281 } 282 283 // Make a public link 284 func rcPublicLink(ctx context.Context, in rc.Params) (out rc.Params, err error) { 285 f, remote, err := rc.GetFsAndRemote(in) 286 if err != nil { 287 return nil, err 288 } 289 url, err := PublicLink(ctx, f, remote) 290 if err != nil { 291 return nil, err 292 } 293 out = make(rc.Params) 294 out["url"] = url 295 return out, nil 296 } 297 298 func init() { 299 rc.Add(rc.Call{ 300 Path: "operations/fsinfo", 301 Fn: rcFsInfo, 302 Title: "Return information about the remote", 303 Help: `This takes the following parameters 304 305 - fs - a remote name string eg "drive:" 306 307 This returns info about the remote passed in; 308 309 ` + "```" + ` 310 { 311 // optional features and whether they are available or not 312 "Features": { 313 "About": true, 314 "BucketBased": false, 315 "CanHaveEmptyDirectories": true, 316 "CaseInsensitive": false, 317 "ChangeNotify": false, 318 "CleanUp": false, 319 "Copy": false, 320 "DirCacheFlush": false, 321 "DirMove": true, 322 "DuplicateFiles": false, 323 "GetTier": false, 324 "ListR": false, 325 "MergeDirs": false, 326 "Move": true, 327 "OpenWriterAt": true, 328 "PublicLink": false, 329 "Purge": true, 330 "PutStream": true, 331 "PutUnchecked": false, 332 "ReadMimeType": false, 333 "ServerSideAcrossConfigs": false, 334 "SetTier": false, 335 "SetWrapper": false, 336 "UnWrap": false, 337 "WrapFs": false, 338 "WriteMimeType": false 339 }, 340 // Names of hashes available 341 "Hashes": [ 342 "MD5", 343 "SHA-1", 344 "DropboxHash", 345 "QuickXorHash" 346 ], 347 "Name": "local", // Name as created 348 "Precision": 1, // Precision of timestamps in ns 349 "Root": "/", // Path as created 350 "String": "Local file system at /" // how the remote will appear in logs 351 } 352 ` + "```" + ` 353 354 This command does not have a command line equivalent so use this instead: 355 356 rclone rc --loopback operations/fsinfo fs=remote: 357 358 `, 359 }) 360 } 361 362 // Fsinfo the remote 363 func rcFsInfo(ctx context.Context, in rc.Params) (out rc.Params, err error) { 364 f, err := rc.GetFs(in) 365 if err != nil { 366 return nil, err 367 } 368 info := GetFsInfo(f) 369 err = rc.Reshape(&out, info) 370 if err != nil { 371 return nil, errors.Wrap(err, "fsinfo Reshape failed") 372 } 373 return out, nil 374 }