diff --git a/b2/b2.go b/b2/b2.go index 553de9e15..b1b57ef02 100644 --- a/b2/b2.go +++ b/b2/b2.go @@ -595,6 +595,12 @@ func (f *Fs) List(out fs.ListOpts, dir string) { return } +// ListR lists the objects and directories of the Fs starting +// from dir recursively into out. +func (f *Fs) ListR(out fs.ListOpts, dir string) { + f.List(out, dir) // FIXME +} + // listBucketFn is called from listBucketsToFn to handle a bucket type listBucketFn func(*api.Bucket) error @@ -1365,6 +1371,7 @@ var ( _ fs.Fs = &Fs{} _ fs.Purger = &Fs{} _ fs.CleanUpper = &Fs{} + _ fs.ListRer = &Fs{} _ fs.Object = &Object{} _ fs.MimeTyper = &Object{} ) diff --git a/dropbox/dropbox.go b/dropbox/dropbox.go index e4bb10dcc..2d6696e8d 100644 --- a/dropbox/dropbox.go +++ b/dropbox/dropbox.go @@ -16,6 +16,9 @@ API v1, and at least the last path component will have the correct 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. */ import ( diff --git a/fs/fs.go b/fs/fs.go index bf44d1a22..57777dd9d 100644 --- a/fs/fs.go +++ b/fs/fs.go @@ -295,6 +295,19 @@ type Features struct { // Implement this if you have a way of emptying the trash or // otherwise cleaning up old versions of files. CleanUp func() error + + // ListR lists the objects and directories of the Fs starting + // from dir recursively into out. + // + // dir should be "" to start from the root, and should not + // have trailing slashes. + // + // This should return ErrDirNotFound (using out.SetError()) + // if the directory isn't found. + // + // Don't implement this unless you have a more efficient way + // of listing recursively that doing a directory traversal. + ListR func(out ListOpts, dir string) } // Fill fills in the function pointers in the Features struct from the @@ -328,6 +341,9 @@ func (ft *Features) Fill(f Fs) *Features { if do, ok := f.(CleanUpper); ok { ft.CleanUp = do.CleanUp } + if do, ok := f.(ListRer); ok { + ft.ListR = do.ListR + } return ft } @@ -370,6 +386,9 @@ func (ft *Features) Mask(f Fs) *Features { if mask.CleanUp == nil { ft.CleanUp = nil } + if mask.ListR == nil { + ft.ListR = nil + } return ft } @@ -479,6 +498,22 @@ type CleanUpper interface { CleanUp() error } +// ListRer is an optional interfaces for Fs +type ListRer interface { + // ListR lists the objects and directories of the Fs starting + // from dir recursively into out. + // + // dir should be "" to start from the root, and should not + // have trailing slashes. + // + // This should return ErrDirNotFound (using out.SetError()) + // if the directory isn't found. + // + // Don't implement this unless you have a more efficient way + // of listing recursively that doing a directory traversal. + ListR(out ListOpts, dir string) +} + // ObjectsChan is a channel of Objects type ObjectsChan chan Object diff --git a/googlecloudstorage/googlecloudstorage.go b/googlecloudstorage/googlecloudstorage.go index c72f5dcd8..a7b459496 100644 --- a/googlecloudstorage/googlecloudstorage.go +++ b/googlecloudstorage/googlecloudstorage.go @@ -443,6 +443,12 @@ func (f *Fs) List(out fs.ListOpts, dir string) { return } +// ListR lists the objects and directories of the Fs starting +// from dir recursively into out. +func (f *Fs) ListR(out fs.ListOpts, dir string) { + f.List(out, dir) // FIXME +} + // Put the object into the bucket // // Copy the reader in to the new object which is returned @@ -736,6 +742,7 @@ func (o *Object) MimeType() string { var ( _ fs.Fs = &Fs{} _ fs.Copier = &Fs{} + _ fs.ListRer = &Fs{} _ fs.Object = &Object{} _ fs.MimeTyper = &Object{} ) diff --git a/s3/s3.go b/s3/s3.go index 44729038f..0af186cdb 100644 --- a/s3/s3.go +++ b/s3/s3.go @@ -626,6 +626,12 @@ func (f *Fs) List(out fs.ListOpts, dir string) { return } +// ListR lists the objects and directories of the Fs starting +// from dir recursively into out. +func (f *Fs) ListR(out fs.ListOpts, dir string) { + f.List(out, dir) // FIXME +} + // Put the Object into the bucket func (f *Fs) Put(in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) (fs.Object, error) { // Temporary Object under construction @@ -998,6 +1004,7 @@ func (o *Object) MimeType() string { var ( _ fs.Fs = &Fs{} _ fs.Copier = &Fs{} + _ fs.ListRer = &Fs{} _ fs.Object = &Object{} _ fs.MimeTyper = &Object{} ) diff --git a/swift/swift.go b/swift/swift.go index 6d1e49bc9..07034e73a 100644 --- a/swift/swift.go +++ b/swift/swift.go @@ -397,6 +397,12 @@ func (f *Fs) List(out fs.ListOpts, dir string) { return } +// ListR lists the objects and directories of the Fs starting +// from dir recursively into out. +func (f *Fs) ListR(out fs.ListOpts, dir string) { + f.List(out, dir) // FIXME +} + // Put the object into the container // // Copy the reader in to the new object which is returned @@ -830,6 +836,7 @@ var ( _ fs.Fs = &Fs{} _ fs.Purger = &Fs{} _ fs.Copier = &Fs{} + _ fs.ListRer = &Fs{} _ fs.Object = &Object{} _ fs.MimeTyper = &Object{} ) diff --git a/yandex/yandex.go b/yandex/yandex.go index 099bd1403..5b16f134f 100644 --- a/yandex/yandex.go +++ b/yandex/yandex.go @@ -326,6 +326,12 @@ func (f *Fs) List(out fs.ListOpts, dir string) { } } +// ListR lists the objects and directories of the Fs starting +// from dir recursively into out. +func (f *Fs) ListR(out fs.ListOpts, dir string) { + f.List(out, dir) // FIXME +} + // NewObject finds the Object at remote. If it can't be found it // returns the error fs.ErrorObjectNotFound. func (f *Fs) NewObject(remote string) (fs.Object, error) { @@ -647,8 +653,9 @@ func (o *Object) MimeType() string { // Check the interfaces are satisfied var ( - _ fs.Fs = (*Fs)(nil) - _ fs.Purger = (*Fs)(nil) + _ fs.Fs = (*Fs)(nil) + _ fs.Purger = (*Fs)(nil) + _ fs.ListRer = (*Fs)(nil) //_ fs.Copier = (*Fs)(nil) _ fs.Object = (*Object)(nil) _ fs.MimeTyper = &Object{}