Get rid of LimitedFs - FIXME needs docs on copying single files

If remote:path points to a file make NewFs return a sentinel error
fs.ErrorIsFile and an Fs which points to the parent.

Use this to remove the LimitedFs and just add this file to the
--files-from list.

This means that server side operations can be used also.

Fixes #518
Fixes #545
s3-about
Nick Craig-Wood 2016-06-21 18:01:53 +01:00
parent 5a3b109e25
commit 1a87b69376
26 changed files with 101 additions and 239 deletions

View File

@ -220,8 +220,8 @@ func NewFs(name, root string) (fs.Fs, error) {
// File doesn't exist so return old f
return f, nil
}
// return a Fs Limited to this object
return fs.NewLimited(&newF, obj), nil
// return an error with an fs which points to the parent
return &newF, fs.ErrorIsFile
}
return f, nil
}

View File

@ -51,8 +51,8 @@ func TestObjectSize(t *testing.T) { fstests.TestObjectSize(t) }
func TestObjectOpen(t *testing.T) { fstests.TestObjectOpen(t) }
func TestObjectUpdate(t *testing.T) { fstests.TestObjectUpdate(t) }
func TestObjectStorable(t *testing.T) { fstests.TestObjectStorable(t) }
func TestLimitedFs(t *testing.T) { fstests.TestLimitedFs(t) }
func TestLimitedFsNotFound(t *testing.T) { fstests.TestLimitedFsNotFound(t) }
func TestFsIsFile(t *testing.T) { fstests.TestFsIsFile(t) }
func TestFsIsFileNotFound(t *testing.T) { fstests.TestFsIsFileNotFound(t) }
func TestObjectRemove(t *testing.T) { fstests.TestObjectRemove(t) }
func TestObjectPurge(t *testing.T) { fstests.TestObjectPurge(t) }
func TestFinalise(t *testing.T) { fstests.TestFinalise(t) }

View File

@ -239,7 +239,8 @@ func NewFs(name, root string) (fs.Fs, error) {
}
obj := f.NewFsObject(remote)
if obj != nil {
return fs.NewLimited(f, obj), nil
// return an error with an fs which points to the parent
return f, fs.ErrorIsFile
}
f.root = oldRoot
}

View File

@ -51,8 +51,8 @@ func TestObjectSize(t *testing.T) { fstests.TestObjectSize(t) }
func TestObjectOpen(t *testing.T) { fstests.TestObjectOpen(t) }
func TestObjectUpdate(t *testing.T) { fstests.TestObjectUpdate(t) }
func TestObjectStorable(t *testing.T) { fstests.TestObjectStorable(t) }
func TestLimitedFs(t *testing.T) { fstests.TestLimitedFs(t) }
func TestLimitedFsNotFound(t *testing.T) { fstests.TestLimitedFsNotFound(t) }
func TestFsIsFile(t *testing.T) { fstests.TestFsIsFile(t) }
func TestFsIsFileNotFound(t *testing.T) { fstests.TestFsIsFileNotFound(t) }
func TestObjectRemove(t *testing.T) { fstests.TestObjectRemove(t) }
func TestObjectPurge(t *testing.T) { fstests.TestObjectPurge(t) }
func TestFinalise(t *testing.T) { fstests.TestFinalise(t) }

View File

@ -337,13 +337,13 @@ func NewFs(name, path string) (fs.Fs, error) {
// No root so return old f
return f, nil
}
obj, err := newF.newFsObjectWithInfoErr(remote, nil)
_, err := newF.newFsObjectWithInfoErr(remote, nil)
if err != nil {
// File doesn't exist so return old f
return f, nil
}
// return a Fs Limited to this object
return fs.NewLimited(&newF, obj), nil
// return an error with an fs which points to the parent
return &newF, fs.ErrorIsFile
}
// fmt.Printf("Root id %s", f.dirCache.RootID())
return f, nil

View File

@ -51,8 +51,8 @@ func TestObjectSize(t *testing.T) { fstests.TestObjectSize(t) }
func TestObjectOpen(t *testing.T) { fstests.TestObjectOpen(t) }
func TestObjectUpdate(t *testing.T) { fstests.TestObjectUpdate(t) }
func TestObjectStorable(t *testing.T) { fstests.TestObjectStorable(t) }
func TestLimitedFs(t *testing.T) { fstests.TestLimitedFs(t) }
func TestLimitedFsNotFound(t *testing.T) { fstests.TestLimitedFsNotFound(t) }
func TestFsIsFile(t *testing.T) { fstests.TestFsIsFile(t) }
func TestFsIsFileNotFound(t *testing.T) { fstests.TestFsIsFileNotFound(t) }
func TestObjectRemove(t *testing.T) { fstests.TestObjectRemove(t) }
func TestObjectPurge(t *testing.T) { fstests.TestObjectPurge(t) }
func TestFinalise(t *testing.T) { fstests.TestFinalise(t) }

View File

@ -172,15 +172,13 @@ func NewFs(name, root string) (fs.Fs, error) {
// See if the root is actually an object
entry, err := f.db.Metadata(f.slashRoot, false, false, "", "", metadataLimit)
if err == nil && !entry.IsDir {
remote := path.Base(f.root)
newRoot := path.Dir(f.root)
if newRoot == "." {
newRoot = ""
}
f.setRoot(newRoot)
obj := f.NewFsObject(remote)
// return a Fs Limited to this object
return fs.NewLimited(f, obj), nil
// return an error with an fs which points to the parent
return f, fs.ErrorIsFile
}
return f, nil

View File

@ -51,8 +51,8 @@ func TestObjectSize(t *testing.T) { fstests.TestObjectSize(t) }
func TestObjectOpen(t *testing.T) { fstests.TestObjectOpen(t) }
func TestObjectUpdate(t *testing.T) { fstests.TestObjectUpdate(t) }
func TestObjectStorable(t *testing.T) { fstests.TestObjectStorable(t) }
func TestLimitedFs(t *testing.T) { fstests.TestLimitedFs(t) }
func TestLimitedFsNotFound(t *testing.T) { fstests.TestLimitedFsNotFound(t) }
func TestFsIsFile(t *testing.T) { fstests.TestFsIsFile(t) }
func TestFsIsFileNotFound(t *testing.T) { fstests.TestFsIsFileNotFound(t) }
func TestObjectRemove(t *testing.T) { fstests.TestObjectRemove(t) }
func TestObjectPurge(t *testing.T) { fstests.TestObjectPurge(t) }
func TestFinalise(t *testing.T) { fstests.TestFinalise(t) }

View File

@ -42,6 +42,7 @@ var (
ErrorLevelNotSupported = errors.New("level value not supported")
ErrorListAborted = errors.New("list aborted")
ErrorListOnlyRoot = errors.New("can only list from root")
ErrorIsFile = errors.New("is a file not a directory")
)
// RegInfo provides information about a filesystem
@ -51,8 +52,8 @@ type RegInfo struct {
// Description of this fs - defaults to Name
Description string
// Create a new file system. If root refers to an existing
// object, then it should return a Fs which only returns that
// object.
// object, then it should return a Fs which which points to
// the parent of that object and ErrorIsFile.
NewFs func(name string, root string) (Fs, error)
// Function to call to help with config
Config func(string)
@ -347,6 +348,26 @@ func Find(name string) (*RegInfo, error) {
// Pattern to match an rclone url
var matcher = regexp.MustCompile(`^([\w_ -]+):(.*)$`)
// ParseRemote deconstructs a path into configName, fsPath, looking up
// the fsName in the config file (returning NotFoundInConfigFile if not found)
func ParseRemote(path string) (fsInfo *RegInfo, configName, fsPath string, err error) {
parts := matcher.FindStringSubmatch(path)
var fsName string
fsName, configName, fsPath = "local", "local", path
if parts != nil && !isDriveLetter(parts[1]) {
configName, fsPath = parts[1], parts[2]
var err error
fsName, err = ConfigFile.GetValue(configName, "type")
if err != nil {
return nil, "", "", ErrorNotFoundInConfigFile
}
}
// change native directory separators to / if there are any
fsPath = filepath.ToSlash(fsPath)
fsInfo, err = Find(fsName)
return fsInfo, configName, fsPath, err
}
// NewFs makes a new Fs object from the path
//
// The path is of the form remote:path
@ -357,23 +378,11 @@ var matcher = regexp.MustCompile(`^([\w_ -]+):(.*)$`)
// On Windows avoid single character remote names as they can be mixed
// up with drive letters.
func NewFs(path string) (Fs, error) {
parts := matcher.FindStringSubmatch(path)
fsName, configName, fsPath := "local", "local", path
if parts != nil && !isDriveLetter(parts[1]) {
configName, fsPath = parts[1], parts[2]
var err error
fsName, err = ConfigFile.GetValue(configName, "type")
if err != nil {
return nil, ErrorNotFoundInConfigFile
}
}
fs, err := Find(fsName)
fsInfo, configName, fsPath, err := ParseRemote(path)
if err != nil {
return nil, err
}
// change native directory separators to / if there are any
fsPath = filepath.ToSlash(fsPath)
return fs.NewFs(configName, fsPath)
return fsInfo.NewFs(configName, fsPath)
}
// DebugLogger - logs to Stdout

View File

@ -1,147 +0,0 @@
package fs
import (
"fmt"
"io"
"time"
"github.com/pkg/errors"
)
// 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, dir string) {
defer opts.Finished()
if dir != "" {
opts.SetError(ErrorListOnlyRoot)
return
}
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, errors.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)
)

View File

@ -608,31 +608,20 @@ func TestObjectStorable(t *testing.T) {
}
}
// TestLimitedFs tests that a LimitedFs is created
func TestLimitedFs(t *testing.T) {
// TestFsIsFile tests that an error is returned along with a valid fs
// which points to the parent directory.
func TestFsIsFile(t *testing.T) {
skipIfNotOk(t)
remoteName := subRemoteName + "/" + file2.Path
file2Copy := file2
file2Copy.Path = "z.txt"
fileRemote, err := fs.NewFs(remoteName)
if err != nil {
t.Fatalf("Failed to make remote %q: %v", remoteName, err)
}
assert.Equal(t, fs.ErrorIsFile, err)
fstest.CheckListing(t, fileRemote, []fstest.Item{file2Copy})
_, ok := fileRemote.(*fs.Limited)
if !ok {
// Check to see if this wraps a Limited FS
if unwrap, hasUnWrap := fileRemote.(fs.UnWrapper); hasUnWrap {
_, ok = unwrap.UnWrap().(*fs.Limited)
}
if !ok {
t.Errorf("%v is not a fs.Limited", fileRemote)
}
}
}
// TestLimitedFsNotFound tests that a LimitedFs is not created if no object
func TestLimitedFsNotFound(t *testing.T) {
// TestFsIsFileNotFound tests that an error is not returned if no object is found
func TestFsIsFileNotFound(t *testing.T) {
skipIfNotOk(t)
remoteName := subRemoteName + "/not found.txt"
fileRemote, err := fs.NewFs(remoteName)

View File

@ -252,16 +252,14 @@ func NewFs(name, root string) (fs.Fs, error) {
// Check to see if the object exists
_, err = f.svc.Objects.Get(bucket, directory).Do()
if err == nil {
remote := path.Base(directory)
f.root = path.Dir(directory)
if f.root == "." {
f.root = ""
} else {
f.root += "/"
}
obj := f.NewFsObject(remote)
// return a Fs Limited to this object
return fs.NewLimited(f, obj), nil
// return an error with an fs which points to the parent
return f, fs.ErrorIsFile
}
}
return f, nil

View File

@ -51,8 +51,8 @@ func TestObjectSize(t *testing.T) { fstests.TestObjectSize(t) }
func TestObjectOpen(t *testing.T) { fstests.TestObjectOpen(t) }
func TestObjectUpdate(t *testing.T) { fstests.TestObjectUpdate(t) }
func TestObjectStorable(t *testing.T) { fstests.TestObjectStorable(t) }
func TestLimitedFs(t *testing.T) { fstests.TestLimitedFs(t) }
func TestLimitedFsNotFound(t *testing.T) { fstests.TestLimitedFsNotFound(t) }
func TestFsIsFile(t *testing.T) { fstests.TestFsIsFile(t) }
func TestFsIsFileNotFound(t *testing.T) { fstests.TestFsIsFileNotFound(t) }
func TestObjectRemove(t *testing.T) { fstests.TestObjectRemove(t) }
func TestObjectPurge(t *testing.T) { fstests.TestObjectPurge(t) }
func TestFinalise(t *testing.T) { fstests.TestFinalise(t) }

View File

@ -167,11 +167,11 @@ func NewFs(name, root string) (fs.Fs, error) {
// Make inner swift Fs from the connection
swiftFs, err := swift.NewFsWithConnection(name, root, c)
if err != nil {
if err != nil && err != fs.ErrorIsFile {
return nil, err
}
f.Fs = swiftFs
return f, nil
return f, err
}
// Purge deletes all the files and the container

View File

@ -51,8 +51,8 @@ func TestObjectSize(t *testing.T) { fstests.TestObjectSize(t) }
func TestObjectOpen(t *testing.T) { fstests.TestObjectOpen(t) }
func TestObjectUpdate(t *testing.T) { fstests.TestObjectUpdate(t) }
func TestObjectStorable(t *testing.T) { fstests.TestObjectStorable(t) }
func TestLimitedFs(t *testing.T) { fstests.TestLimitedFs(t) }
func TestLimitedFsNotFound(t *testing.T) { fstests.TestLimitedFsNotFound(t) }
func TestFsIsFile(t *testing.T) { fstests.TestFsIsFile(t) }
func TestFsIsFileNotFound(t *testing.T) { fstests.TestFsIsFileNotFound(t) }
func TestObjectRemove(t *testing.T) { fstests.TestObjectRemove(t) }
func TestObjectPurge(t *testing.T) { fstests.TestObjectPurge(t) }
func TestFinalise(t *testing.T) { fstests.TestFinalise(t) }

View File

@ -82,8 +82,8 @@ func NewFs(name, root string) (fs.Fs, error) {
if obj == nil {
return nil, errors.Errorf("failed to make object for %q in %q", remote, f.root)
}
// return a Fs Limited to this object
return fs.NewLimited(f, obj), nil
// return an error with an fs which points to the parent
return f, fs.ErrorIsFile
}
return f, nil
}

View File

@ -51,8 +51,8 @@ func TestObjectSize(t *testing.T) { fstests.TestObjectSize(t) }
func TestObjectOpen(t *testing.T) { fstests.TestObjectOpen(t) }
func TestObjectUpdate(t *testing.T) { fstests.TestObjectUpdate(t) }
func TestObjectStorable(t *testing.T) { fstests.TestObjectStorable(t) }
func TestLimitedFs(t *testing.T) { fstests.TestLimitedFs(t) }
func TestLimitedFsNotFound(t *testing.T) { fstests.TestLimitedFsNotFound(t) }
func TestFsIsFile(t *testing.T) { fstests.TestFsIsFile(t) }
func TestFsIsFileNotFound(t *testing.T) { fstests.TestFsIsFileNotFound(t) }
func TestObjectRemove(t *testing.T) { fstests.TestObjectRemove(t) }
func TestObjectPurge(t *testing.T) { fstests.TestObjectPurge(t) }
func TestFinalise(t *testing.T) { fstests.TestFinalise(t) }

View File

@ -211,8 +211,8 @@ func NewFs(name, root string) (fs.Fs, error) {
// File doesn't exist so return old f
return f, nil
}
// return a Fs Limited to this object
return fs.NewLimited(&newF, obj), nil
// return an error with an fs which points to the parent
return &newF, fs.ErrorIsFile
}
return f, nil
}

View File

@ -51,8 +51,8 @@ func TestObjectSize(t *testing.T) { fstests.TestObjectSize(t) }
func TestObjectOpen(t *testing.T) { fstests.TestObjectOpen(t) }
func TestObjectUpdate(t *testing.T) { fstests.TestObjectUpdate(t) }
func TestObjectStorable(t *testing.T) { fstests.TestObjectStorable(t) }
func TestLimitedFs(t *testing.T) { fstests.TestLimitedFs(t) }
func TestLimitedFsNotFound(t *testing.T) { fstests.TestLimitedFsNotFound(t) }
func TestFsIsFile(t *testing.T) { fstests.TestFsIsFile(t) }
func TestFsIsFileNotFound(t *testing.T) { fstests.TestFsIsFileNotFound(t) }
func TestObjectRemove(t *testing.T) { fstests.TestObjectRemove(t) }
func TestObjectPurge(t *testing.T) { fstests.TestObjectPurge(t) }
func TestFinalise(t *testing.T) { fstests.TestFinalise(t) }

View File

@ -7,6 +7,7 @@ import (
"fmt"
"log"
"os"
"path"
"runtime"
"runtime/pprof"
"strings"
@ -368,7 +369,29 @@ func ParseCommand() (*Command, []string) {
return command, args
}
// NewFs creates a Fs from a name
// NewFsSrc creates a src Fs from a name
func NewFsSrc(remote string) fs.Fs {
fsInfo, configName, fsPath, err := fs.ParseRemote(remote)
if err != nil {
fs.Stats.Error()
log.Fatalf("Failed to create file system for %q: %v", remote, err)
}
f, err := fsInfo.NewFs(configName, fsPath)
if err == fs.ErrorIsFile {
if !fs.Config.Filter.InActive() {
fs.Stats.Error()
log.Fatalf("Can't limit to single files when using filters: %v", remote)
}
// Limit transfers to this file
fs.Config.Filter.AddFile(path.Base(fsPath))
} else if err != nil {
fs.Stats.Error()
log.Fatalf("Failed to create file system for %q: %v", remote, err)
}
return f
}
// NewFs creates a dst Fs from a name
func NewFs(remote string) fs.Fs {
f, err := fs.NewFs(remote)
if err != nil {
@ -462,7 +485,7 @@ func main() {
// Make source and destination fs
var fdst, fsrc fs.Fs
if len(args) >= 1 {
fdst = NewFs(args[0])
fdst = NewFsSrc(args[0])
}
if len(args) >= 2 {
fsrc = fdst

View File

@ -326,16 +326,14 @@ func NewFs(name, root string) (fs.Fs, error) {
}
_, err = f.c.HeadObject(&req)
if err == nil {
remote := path.Base(directory)
f.root = path.Dir(directory)
if f.root == "." {
f.root = ""
} else {
f.root += "/"
}
obj := f.NewFsObject(remote)
// return a Fs Limited to this object
return fs.NewLimited(f, obj), nil
// return an error with an fs which points to the parent
return f, fs.ErrorIsFile
}
}
// f.listMultipartUploads()

View File

@ -51,8 +51,8 @@ func TestObjectSize(t *testing.T) { fstests.TestObjectSize(t) }
func TestObjectOpen(t *testing.T) { fstests.TestObjectOpen(t) }
func TestObjectUpdate(t *testing.T) { fstests.TestObjectUpdate(t) }
func TestObjectStorable(t *testing.T) { fstests.TestObjectStorable(t) }
func TestLimitedFs(t *testing.T) { fstests.TestLimitedFs(t) }
func TestLimitedFsNotFound(t *testing.T) { fstests.TestLimitedFsNotFound(t) }
func TestFsIsFile(t *testing.T) { fstests.TestFsIsFile(t) }
func TestFsIsFileNotFound(t *testing.T) { fstests.TestFsIsFileNotFound(t) }
func TestObjectRemove(t *testing.T) { fstests.TestObjectRemove(t) }
func TestObjectPurge(t *testing.T) { fstests.TestObjectPurge(t) }
func TestFinalise(t *testing.T) { fstests.TestFinalise(t) }

View File

@ -199,16 +199,14 @@ func NewFsWithConnection(name, root string, c *swift.Connection) (fs.Fs, error)
// Check to see if the object exists - ignoring directory markers
info, _, err := f.c.Object(container, directory)
if err == nil && info.ContentType != directoryMarkerContentType {
remote := path.Base(directory)
f.root = path.Dir(directory)
if f.root == "." {
f.root = ""
} else {
f.root += "/"
}
obj := f.NewFsObject(remote)
// return a Fs Limited to this object
return fs.NewLimited(f, obj), nil
// return an error with an fs which points to the parent
return f, fs.ErrorIsFile
}
}
return f, nil

View File

@ -51,8 +51,8 @@ func TestObjectSize(t *testing.T) { fstests.TestObjectSize(t) }
func TestObjectOpen(t *testing.T) { fstests.TestObjectOpen(t) }
func TestObjectUpdate(t *testing.T) { fstests.TestObjectUpdate(t) }
func TestObjectStorable(t *testing.T) { fstests.TestObjectStorable(t) }
func TestLimitedFs(t *testing.T) { fstests.TestLimitedFs(t) }
func TestLimitedFsNotFound(t *testing.T) { fstests.TestLimitedFsNotFound(t) }
func TestFsIsFile(t *testing.T) { fstests.TestFsIsFile(t) }
func TestFsIsFileNotFound(t *testing.T) { fstests.TestFsIsFileNotFound(t) }
func TestObjectRemove(t *testing.T) { fstests.TestObjectRemove(t) }
func TestObjectPurge(t *testing.T) { fstests.TestObjectPurge(t) }
func TestFinalise(t *testing.T) { fstests.TestFinalise(t) }

View File

@ -128,7 +128,6 @@ func NewFs(name, root string) (fs.Fs, error) {
f.setRoot(root)
//limited fs
// Check to see if the object exists and is a file
//request object meta info
var opt2 yandex.ResourceInfoRequestOptions
@ -136,13 +135,9 @@ func NewFs(name, root string) (fs.Fs, error) {
//return err
} else {
if ResourceInfoResponse.ResourceType == "file" {
//limited fs
remote := path.Base(root)
f.setRoot(path.Dir(root))
obj := f.newFsObjectWithInfo(remote, ResourceInfoResponse)
// return a Fs Limited to this object
return fs.NewLimited(f, obj), nil
// return an error with an fs which points to the parent
return f, fs.ErrorIsFile
}
}

View File

@ -51,8 +51,8 @@ func TestObjectSize(t *testing.T) { fstests.TestObjectSize(t) }
func TestObjectOpen(t *testing.T) { fstests.TestObjectOpen(t) }
func TestObjectUpdate(t *testing.T) { fstests.TestObjectUpdate(t) }
func TestObjectStorable(t *testing.T) { fstests.TestObjectStorable(t) }
func TestLimitedFs(t *testing.T) { fstests.TestLimitedFs(t) }
func TestLimitedFsNotFound(t *testing.T) { fstests.TestLimitedFsNotFound(t) }
func TestFsIsFile(t *testing.T) { fstests.TestFsIsFile(t) }
func TestFsIsFileNotFound(t *testing.T) { fstests.TestFsIsFileNotFound(t) }
func TestObjectRemove(t *testing.T) { fstests.TestObjectRemove(t) }
func TestObjectPurge(t *testing.T) { fstests.TestObjectPurge(t) }
func TestFinalise(t *testing.T) { fstests.TestFinalise(t) }