forked from TrueCloudLab/rclone
operations: make NewOverrideObjectInfo public and factor uses
This commit is contained in:
parent
08a3957880
commit
ef7ac088c0
3 changed files with 70 additions and 22 deletions
|
@ -12,6 +12,7 @@ import (
|
||||||
_ "github.com/rclone/rclone/backend/local"
|
_ "github.com/rclone/rclone/backend/local"
|
||||||
"github.com/rclone/rclone/fs"
|
"github.com/rclone/rclone/fs"
|
||||||
"github.com/rclone/rclone/fs/hash"
|
"github.com/rclone/rclone/fs/hash"
|
||||||
|
"github.com/rclone/rclone/fs/operations"
|
||||||
"github.com/rclone/rclone/fstest"
|
"github.com/rclone/rclone/fstest"
|
||||||
"github.com/rclone/rclone/lib/random"
|
"github.com/rclone/rclone/lib/random"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -26,17 +27,6 @@ const (
|
||||||
fileNameUpload = "rclone-test-image2.jpg"
|
fileNameUpload = "rclone-test-image2.jpg"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Wrapper to override the remote for an object
|
|
||||||
type overrideRemoteObject struct {
|
|
||||||
fs.Object
|
|
||||||
remote string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remote returns the overridden remote name
|
|
||||||
func (o *overrideRemoteObject) Remote() string {
|
|
||||||
return o.remote
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntegration(t *testing.T) {
|
func TestIntegration(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
fstest.Initialise()
|
fstest.Initialise()
|
||||||
|
@ -66,7 +56,7 @@ func TestIntegration(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
in, err := srcObj.Open(ctx)
|
in, err := srcObj.Open(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
dstObj, err := f.Put(ctx, in, &overrideRemoteObject{srcObj, remote})
|
dstObj, err := f.Put(ctx, in, operations.NewOverrideRemote(srcObj, remote))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, remote, dstObj.Remote())
|
assert.Equal(t, remote, dstObj.Remote())
|
||||||
_ = in.Close()
|
_ = in.Close()
|
||||||
|
@ -231,7 +221,7 @@ func TestIntegration(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
in, err := srcObj.Open(ctx)
|
in, err := srcObj.Open(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
dstObj, err := f.Put(ctx, in, &overrideRemoteObject{srcObj, remote})
|
dstObj, err := f.Put(ctx, in, operations.NewOverrideRemote(srcObj, remote))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, remote, dstObj.Remote())
|
assert.Equal(t, remote, dstObj.Remote())
|
||||||
_ = in.Close()
|
_ = in.Close()
|
||||||
|
|
23
fs/fs.go
23
fs/fs.go
|
@ -412,6 +412,29 @@ type GetTierer interface {
|
||||||
GetTier() string
|
GetTier() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FullObjectInfo contains all the read-only optional interfaces
|
||||||
|
//
|
||||||
|
// Use for checking making wrapping ObjectInfos implement everything
|
||||||
|
type FullObjectInfo interface {
|
||||||
|
ObjectInfo
|
||||||
|
MimeTyper
|
||||||
|
IDer
|
||||||
|
ObjectUnWrapper
|
||||||
|
GetTierer
|
||||||
|
}
|
||||||
|
|
||||||
|
// FullObject contains all the optional interfaces for Object
|
||||||
|
//
|
||||||
|
// Use for checking making wrapping Objects implement everything
|
||||||
|
type FullObject interface {
|
||||||
|
Object
|
||||||
|
MimeTyper
|
||||||
|
IDer
|
||||||
|
ObjectUnWrapper
|
||||||
|
GetTierer
|
||||||
|
SetTierer
|
||||||
|
}
|
||||||
|
|
||||||
// ObjectOptionalInterfaces returns the names of supported and
|
// ObjectOptionalInterfaces returns the names of supported and
|
||||||
// unsupported optional interfaces for an Object
|
// unsupported optional interfaces for an Object
|
||||||
func ObjectOptionalInterfaces(o Object) (supported, unsupported []string) {
|
func ObjectOptionalInterfaces(o Object) (supported, unsupported []string) {
|
||||||
|
|
|
@ -261,28 +261,63 @@ func removeFailedCopy(ctx context.Context, dst fs.Object) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper to override the remote for an object
|
// OverrideRemote is a wrapper to override the Remote for an
|
||||||
type overrideRemoteObject struct {
|
// ObjectInfo
|
||||||
fs.Object
|
type OverrideRemote struct {
|
||||||
|
fs.ObjectInfo
|
||||||
remote string
|
remote string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewOverrideRemote returns an OverrideRemoteObject which will
|
||||||
|
// return the remote specified
|
||||||
|
func NewOverrideRemote(oi fs.ObjectInfo, remote string) *OverrideRemote {
|
||||||
|
return &OverrideRemote{
|
||||||
|
ObjectInfo: oi,
|
||||||
|
remote: remote,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remote returns the overridden remote name
|
// Remote returns the overridden remote name
|
||||||
func (o *overrideRemoteObject) Remote() string {
|
func (o *OverrideRemote) Remote() string {
|
||||||
return o.remote
|
return o.remote
|
||||||
}
|
}
|
||||||
|
|
||||||
// MimeType returns the mime type of the underlying object or "" if it
|
// MimeType returns the mime type of the underlying object or "" if it
|
||||||
// can't be worked out
|
// can't be worked out
|
||||||
func (o *overrideRemoteObject) MimeType(ctx context.Context) string {
|
func (o *OverrideRemote) MimeType(ctx context.Context) string {
|
||||||
if do, ok := o.Object.(fs.MimeTyper); ok {
|
if do, ok := o.ObjectInfo.(fs.MimeTyper); ok {
|
||||||
return do.MimeType(ctx)
|
return do.MimeType(ctx)
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check interface is satisfied
|
// ID returns the ID of the Object if known, or "" if not
|
||||||
var _ fs.MimeTyper = (*overrideRemoteObject)(nil)
|
func (o *OverrideRemote) ID() string {
|
||||||
|
if do, ok := o.ObjectInfo.(fs.IDer); ok {
|
||||||
|
return do.ID()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnWrap returns the Object that this Object is wrapping or nil if it
|
||||||
|
// isn't wrapping anything
|
||||||
|
func (o *OverrideRemote) UnWrap() fs.Object {
|
||||||
|
if o, ok := o.ObjectInfo.(fs.Object); ok {
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTier returns storage tier or class of the Object
|
||||||
|
func (o *OverrideRemote) GetTier() string {
|
||||||
|
if do, ok := o.ObjectInfo.(fs.GetTierer); ok {
|
||||||
|
return do.GetTier()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check all optional interfaces satisfied
|
||||||
|
var _ fs.FullObjectInfo = (*OverrideRemote)(nil)
|
||||||
|
|
||||||
// Copy src object to dst or f if nil. If dst is nil then it uses
|
// Copy src object to dst or f if nil. If dst is nil then it uses
|
||||||
// remote as the name of the new object.
|
// remote as the name of the new object.
|
||||||
|
@ -378,7 +413,7 @@ func Copy(ctx context.Context, f fs.Fs, dst fs.Object, remote string, src fs.Obj
|
||||||
var wrappedSrc fs.ObjectInfo = src
|
var wrappedSrc fs.ObjectInfo = src
|
||||||
// We try to pass the original object if possible
|
// We try to pass the original object if possible
|
||||||
if src.Remote() != remote {
|
if src.Remote() != remote {
|
||||||
wrappedSrc = &overrideRemoteObject{Object: src, remote: remote}
|
wrappedSrc = NewOverrideRemote(src, remote)
|
||||||
}
|
}
|
||||||
if doUpdate {
|
if doUpdate {
|
||||||
actionTaken = "Copied (replaced existing)"
|
actionTaken = "Copied (replaced existing)"
|
||||||
|
|
Loading…
Reference in a new issue