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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user