753b0717be
Gives more accurate error propagation, control of depth of recursion and short circuit recursion where possible. Most of the the heavy lifting is done in the "fs" package, making file system implementations a bit simpler. This commit contains some code originally by Klaus Post. Fixes #316
141 lines
3.3 KiB
Go
141 lines
3.3 KiB
Go
package fs
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"time"
|
|
)
|
|
|
|
// Limited defines a Fs which can only return the Objects passed in
|
|
// from the Fs passed in
|
|
type Limited struct {
|
|
objects []Object
|
|
fs Fs
|
|
}
|
|
|
|
// NewLimited maks a limited Fs limited to the objects passed in
|
|
func NewLimited(fs Fs, objects ...Object) Fs {
|
|
f := &Limited{
|
|
objects: objects,
|
|
fs: fs,
|
|
}
|
|
return f
|
|
}
|
|
|
|
// Name is name of the remote (as passed into NewFs)
|
|
func (f *Limited) Name() string {
|
|
return f.fs.Name() // return name of underlying remote
|
|
}
|
|
|
|
// Root is the root of the remote (as passed into NewFs)
|
|
func (f *Limited) Root() string {
|
|
return f.fs.Root() // return root of underlying remote
|
|
}
|
|
|
|
// String returns a description of the FS
|
|
func (f *Limited) String() string {
|
|
return fmt.Sprintf("%s limited to %d objects", f.fs.String(), len(f.objects))
|
|
}
|
|
|
|
// List the Fs into a channel
|
|
func (f *Limited) List(opts ListOpts) {
|
|
defer opts.Finished()
|
|
for _, obj := range f.objects {
|
|
if opts.Add(obj) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// NewFsObject finds the Object at remote. Returns nil if can't be found
|
|
func (f *Limited) NewFsObject(remote string) Object {
|
|
for _, obj := range f.objects {
|
|
if obj.Remote() == remote {
|
|
return obj
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Put in to the remote path with the modTime given of the given size
|
|
//
|
|
// May create the object even if it returns an error - if so
|
|
// will return the object and the error, otherwise will return
|
|
// nil and the error
|
|
func (f *Limited) Put(in io.Reader, src ObjectInfo) (Object, error) {
|
|
remote := src.Remote()
|
|
obj := f.NewFsObject(remote)
|
|
if obj == nil {
|
|
return nil, fmt.Errorf("Can't create %q in limited fs", remote)
|
|
}
|
|
return obj, obj.Update(in, src)
|
|
}
|
|
|
|
// Mkdir make the directory (container, bucket)
|
|
func (f *Limited) Mkdir() error {
|
|
// All directories are already made - just ignore
|
|
return nil
|
|
}
|
|
|
|
// Rmdir removes the directory (container, bucket) if empty
|
|
func (f *Limited) Rmdir() error {
|
|
// Ignore this in a limited fs
|
|
return nil
|
|
}
|
|
|
|
// Precision of the ModTimes in this Fs
|
|
func (f *Limited) Precision() time.Duration {
|
|
return f.fs.Precision()
|
|
}
|
|
|
|
// Hashes returns the supported hash sets.
|
|
func (f *Limited) Hashes() HashSet {
|
|
return f.fs.Hashes()
|
|
}
|
|
|
|
// Copy src to this remote using server side copy operations.
|
|
//
|
|
// This is stored with the remote path given
|
|
//
|
|
// It returns the destination Object and a possible error
|
|
//
|
|
// Will only be called if src.Fs().Name() == f.Name()
|
|
//
|
|
// If it isn't possible then return fs.ErrorCantCopy
|
|
func (f *Limited) Copy(src Object, remote string) (Object, error) {
|
|
fCopy, ok := f.fs.(Copier)
|
|
if !ok {
|
|
return nil, ErrorCantCopy
|
|
}
|
|
return fCopy.Copy(src, remote)
|
|
}
|
|
|
|
// Move src to this remote using server side move operations.
|
|
//
|
|
// This is stored with the remote path given
|
|
//
|
|
// It returns the destination Object and a possible error
|
|
//
|
|
// Will only be called if src.Fs().Name() == f.Name()
|
|
//
|
|
// If it isn't possible then return fs.ErrorCantMove
|
|
func (f *Limited) Move(src Object, remote string) (Object, error) {
|
|
fMove, ok := f.fs.(Mover)
|
|
if !ok {
|
|
return nil, ErrorCantMove
|
|
}
|
|
return fMove.Move(src, remote)
|
|
}
|
|
|
|
// UnWrap returns the Fs that this Fs is wrapping
|
|
func (f *Limited) UnWrap() Fs {
|
|
return f.fs
|
|
}
|
|
|
|
// Check the interfaces are satisfied
|
|
var (
|
|
_ Fs = (*Limited)(nil)
|
|
_ Copier = (*Limited)(nil)
|
|
_ Mover = (*Limited)(nil)
|
|
_ UnWrapper = (*Limited)(nil)
|
|
)
|