diff --git a/backend/storj/fs.go b/backend/storj/fs.go index ed3004099..0f941e5de 100644 --- a/backend/storj/fs.go +++ b/backend/storj/fs.go @@ -162,6 +162,7 @@ var ( _ fs.PutStreamer = &Fs{} _ fs.Mover = &Fs{} _ fs.Copier = &Fs{} + _ fs.Purger = &Fs{} _ fs.PublicLinker = &Fs{} ) @@ -774,15 +775,63 @@ func (f *Fs) Copy(ctx context.Context, src fs.Object, remote string) (fs.Object, return newObjectFromUplink(f, remote, newObject), nil } +// Purge all files in the directory specified +// +// Implement this if you have a way of deleting all the files +// quicker than just running Remove() on the result of List() +// +// Return an error if it doesn't exist +func (f *Fs) Purge(ctx context.Context, dir string) error { + bucket, directory := f.absolute(dir) + if bucket == "" { + return errors.New("can't purge from root") + } + + if directory == "" { + _, err := f.project.DeleteBucketWithObjects(ctx, bucket) + if errors.Is(err, uplink.ErrBucketNotFound) { + return fs.ErrorDirNotFound + } + return err + } + + fs.Infof(directory, "Quick delete is available only for entire bucket. Falling back to list and delete.") + objects := f.project.ListObjects(ctx, bucket, + &uplink.ListObjectsOptions{ + Prefix: directory + "/", + Recursive: true, + }, + ) + if err := objects.Err(); err != nil { + return err + } + + empty := true + for objects.Next() { + empty = false + _, err := f.project.DeleteObject(ctx, bucket, objects.Item().Key) + if err != nil { + return err + } + fs.Infof(objects.Item().Key, "Deleted") + } + + if empty { + return fs.ErrorDirNotFound + } + + return nil +} + // PublicLink generates a public link to the remote path (usually readable by anyone) func (f *Fs) PublicLink(ctx context.Context, remote string, expire fs.Duration, unlink bool) (string, error) { bucket, key := f.absolute(remote) - if len(bucket) == 0 { + if bucket == "" { return "", errors.New("path must be specified") } // Rclone requires that a link is only generated if the remote path exists - if len(key) == 0 { + if key == "" { _, err := f.project.StatBucket(ctx, bucket) if err != nil { return "", err diff --git a/docs/content/overview.md b/docs/content/overview.md index df19d05a9..a9605c480 100644 --- a/docs/content/overview.md +++ b/docs/content/overview.md @@ -504,7 +504,7 @@ upon backend-specific capabilities. | Sia | No | No | No | No | No | No | Yes | No | No | Yes | | SMB | No | No | Yes | Yes | No | No | Yes | No | No | Yes | | SugarSync | Yes | Yes | Yes | Yes | No | No | Yes | Yes | No | Yes | -| Storj | Yes † | Yes | Yes | No | No | Yes | Yes | Yes | No | No | +| Storj | Yes ☨ | Yes | Yes | No | No | Yes | Yes | Yes | No | No | | Uptobox | No | Yes | Yes | Yes | No | No | No | No | No | No | | WebDAV | Yes | Yes | Yes | Yes | No | No | Yes ‡ | No | Yes | Yes | | Yandex Disk | Yes | Yes | Yes | Yes | Yes | No | Yes | Yes | Yes | Yes | @@ -516,9 +516,12 @@ upon backend-specific capabilities. This deletes a directory quicker than just deleting all the files in the directory. -† Note Swift and Storj implement this in order to delete -directory markers but they don't actually have a quicker way of deleting -files other than deleting them individually. +† Note Swift implements this in order to delete directory markers but +they don't actually have a quicker way of deleting files other than +deleting them individually. + +☨ Storj implements this efficiently only for entire buckets. If +purging a directory inside a bucket, files are deleted individually. ‡ StreamUpload is not supported with Nextcloud