1
0
mirror of https://github.com/rclone/rclone.git synced 2026-01-03 09:03:50 +00:00

Change List interface and add ListR optional interface

This simplifies the implementation of remotes.  The only required
interface is now `List` which is a simple one level directory list.

Optionally remotes may implement `ListR` if they have an efficient way
of doing a recursive list.
This commit is contained in:
Nick Craig-Wood
2017-06-11 22:43:31 +01:00
parent 6fc88ff32e
commit 8a6a8b9623
37 changed files with 994 additions and 1636 deletions

View File

@@ -5,9 +5,9 @@ package dropbox
// FIXME dropbox for business would be quite easy to add
/*
FIXME is case folding of PathDisplay going to cause a problem?
The Case folding of PathDisplay problem
From the docs
From the docs:
path_display String. The cased path to be used for display purposes
only. In rare instances the casing will not correctly match the user's
@@ -17,8 +17,7 @@ casing. Changes to only the casing of paths won't be returned by
list_folder/continue. This field will be null if the file or folder is
not mounted. This field is optional.
This only becomes a problem if dropbox implements the ListR interface
which it currently doesn't.
We solve this by not implementing the ListR interface. The dropbox remote will recurse directory by directory and all will be well.
*/
import (
@@ -315,8 +314,16 @@ func (f *Fs) stripRoot(path string) (string, error) {
return strip(path, f.slashRootSlash)
}
// Walk the root returning a channel of Objects
func (f *Fs) list(out fs.ListOpts, dir string, recursive bool) {
// List the objects and directories in dir into entries. The
// entries can be returned in any order but should be for a
// complete directory.
//
// dir should be "" to list the root, and should not have
// trailing slashes.
//
// This should return ErrDirNotFound if the directory isn't
// found.
func (f *Fs) List(dir string) (entries fs.DirEntries, err error) {
root := f.slashRoot
if dir != "" {
root += "/" + dir
@@ -324,12 +331,11 @@ func (f *Fs) list(out fs.ListOpts, dir string, recursive bool) {
started := false
var res *files.ListFolderResult
var err error
for {
if !started {
arg := files.ListFolderArg{
Path: root,
Recursive: recursive,
Recursive: false,
}
if root == "/" {
arg.Path = "" // Specify root folder as empty string
@@ -346,8 +352,7 @@ func (f *Fs) list(out fs.ListOpts, dir string, recursive bool) {
err = fs.ErrorDirNotFound
}
}
out.SetError(err)
return
return nil, err
}
started = false
} else {
@@ -359,8 +364,7 @@ func (f *Fs) list(out fs.ListOpts, dir string, recursive bool) {
return shouldRetry(err)
})
if err != nil {
out.SetError(errors.Wrap(err, "list continue"))
return
return nil, errors.Wrap(err, "list continue")
}
}
for _, entry := range res.Entries {
@@ -384,56 +388,36 @@ func (f *Fs) list(out fs.ListOpts, dir string, recursive bool) {
if folderInfo != nil {
name, err := f.stripRoot(entryPath + "/")
if err != nil {
out.SetError(err)
return
return nil, err
}
name = strings.Trim(name, "/")
if name != "" && name != dir {
dir := &fs.Dir{
d := &fs.Dir{
Name: name,
When: time.Now(),
//When: folderInfo.ClientMtime,
//Bytes: folderInfo.Bytes,
//Count: -1,
}
if out.AddDir(dir) {
return
}
entries = append(entries, d)
}
} else if fileInfo != nil {
path, err := f.stripRoot(entryPath)
if err != nil {
out.SetError(err)
return
return nil, err
}
o, err := f.newObjectWithInfo(path, fileInfo)
if err != nil {
out.SetError(err)
return
}
if out.Add(o) {
return
return nil, err
}
entries = append(entries, o)
}
}
if !res.HasMore {
break
}
}
}
// List walks the path returning a channel of Objects
func (f *Fs) List(out fs.ListOpts, dir string) {
defer out.Finished()
level := out.Level()
switch level {
case 1:
f.list(out, dir, false)
case fs.MaxLevel:
f.list(out, dir, true)
default:
out.SetError(fs.ErrorLevelNotSupported)
}
return entries, nil
}
// A read closer which doesn't close the input