mirror of
https://github.com/rclone/rclone.git
synced 2024-11-26 10:25:03 +01:00
union: support metadata
This commit is contained in:
parent
bf4a16ae30
commit
ed87ae51c0
@ -2,6 +2,7 @@ package union
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -34,9 +35,8 @@ type entry interface {
|
|||||||
candidates() []upstream.Entry
|
candidates() []upstream.Entry
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnWrap returns the Object that this Object is wrapping or
|
// UnWrapUpstream returns the upstream Object that this Object is wrapping
|
||||||
// nil if it isn't wrapping anything
|
func (o *Object) UnWrapUpstream() *upstream.Object {
|
||||||
func (o *Object) UnWrap() *upstream.Object {
|
|
||||||
return o.Object
|
return o.Object
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,6 +140,42 @@ func (o *Object) SetModTime(ctx context.Context, t time.Time) error {
|
|||||||
return errs.Err()
|
return errs.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTier returns storage tier or class of the Object
|
||||||
|
func (o *Object) GetTier() string {
|
||||||
|
do, ok := o.Object.Object.(fs.GetTierer)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return do.GetTier()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID returns the ID of the Object if known, or "" if not
|
||||||
|
func (o *Object) ID() string {
|
||||||
|
do, ok := o.Object.Object.(fs.IDer)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return do.ID()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MimeType returns the content type of the Object if known
|
||||||
|
func (o *Object) MimeType(ctx context.Context) (mimeType string) {
|
||||||
|
if do, ok := o.Object.Object.(fs.MimeTyper); ok {
|
||||||
|
mimeType = do.MimeType(ctx)
|
||||||
|
}
|
||||||
|
return mimeType
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTier performs changing storage tier of the Object if
|
||||||
|
// multiple storage classes supported
|
||||||
|
func (o *Object) SetTier(tier string) error {
|
||||||
|
do, ok := o.Object.Object.(fs.SetTierer)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("underlying remote does not support SetTier")
|
||||||
|
}
|
||||||
|
return do.SetTier(tier)
|
||||||
|
}
|
||||||
|
|
||||||
// ModTime returns the modification date of the directory
|
// ModTime returns the modification date of the directory
|
||||||
// It returns the latest ModTime of all candidates
|
// It returns the latest ModTime of all candidates
|
||||||
func (d *Directory) ModTime(ctx context.Context) (t time.Time) {
|
func (d *Directory) ModTime(ctx context.Context) (t time.Time) {
|
||||||
@ -164,3 +200,8 @@ func (d *Directory) Size() (s int64) {
|
|||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check the interfaces are satisfied
|
||||||
|
var (
|
||||||
|
_ fs.FullObject = (*Object)(nil)
|
||||||
|
)
|
||||||
|
@ -30,6 +30,9 @@ func init() {
|
|||||||
Name: "union",
|
Name: "union",
|
||||||
Description: "Union merges the contents of several upstream fs",
|
Description: "Union merges the contents of several upstream fs",
|
||||||
NewFs: NewFs,
|
NewFs: NewFs,
|
||||||
|
MetadataInfo: &fs.MetadataInfo{
|
||||||
|
Help: `Any metadata supported by the underlying remote is read and written.`,
|
||||||
|
},
|
||||||
Options: []fs.Option{{
|
Options: []fs.Option{{
|
||||||
Name: "upstreams",
|
Name: "upstreams",
|
||||||
Help: "List of space separated upstreams.\n\nCan be 'upstreama:test/dir upstreamb:', '\"upstreama:test/space:ro dir\" upstreamb:', etc.",
|
Help: "List of space separated upstreams.\n\nCan be 'upstreama:test/dir upstreamb:', '\"upstreama:test/space:ro dir\" upstreamb:', etc.",
|
||||||
@ -219,7 +222,7 @@ func (f *Fs) Copy(ctx context.Context, src fs.Object, remote string) (fs.Object,
|
|||||||
fs.Debugf(src, "Can't copy - not same remote type")
|
fs.Debugf(src, "Can't copy - not same remote type")
|
||||||
return nil, fs.ErrorCantCopy
|
return nil, fs.ErrorCantCopy
|
||||||
}
|
}
|
||||||
o := srcObj.UnWrap()
|
o := srcObj.UnWrapUpstream()
|
||||||
su := o.UpstreamFs()
|
su := o.UpstreamFs()
|
||||||
if su.Features().Copy == nil {
|
if su.Features().Copy == nil {
|
||||||
return nil, fs.ErrorCantCopy
|
return nil, fs.ErrorCantCopy
|
||||||
@ -881,6 +884,9 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
|
|||||||
BucketBased: true,
|
BucketBased: true,
|
||||||
SetTier: true,
|
SetTier: true,
|
||||||
GetTier: true,
|
GetTier: true,
|
||||||
|
ReadMetadata: true,
|
||||||
|
WriteMetadata: true,
|
||||||
|
UserMetadata: true,
|
||||||
}).Fill(ctx, f)
|
}).Fill(ctx, f)
|
||||||
canMove := true
|
canMove := true
|
||||||
for _, f := range upstreams {
|
for _, f := range upstreams {
|
||||||
|
@ -245,6 +245,53 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTier returns storage tier or class of the Object
|
||||||
|
func (o *Object) GetTier() string {
|
||||||
|
do, ok := o.Object.(fs.GetTierer)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return do.GetTier()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID returns the ID of the Object if known, or "" if not
|
||||||
|
func (o *Object) ID() string {
|
||||||
|
do, ok := o.Object.(fs.IDer)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return do.ID()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MimeType returns the content type of the Object if known
|
||||||
|
func (o *Object) MimeType(ctx context.Context) (mimeType string) {
|
||||||
|
if do, ok := o.Object.(fs.MimeTyper); ok {
|
||||||
|
mimeType = do.MimeType(ctx)
|
||||||
|
}
|
||||||
|
return mimeType
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTier performs changing storage tier of the Object if
|
||||||
|
// multiple storage classes supported
|
||||||
|
func (o *Object) SetTier(tier string) error {
|
||||||
|
do, ok := o.Object.(fs.SetTierer)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("underlying remote does not support SetTier")
|
||||||
|
}
|
||||||
|
return do.SetTier(tier)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Metadata returns metadata for an object
|
||||||
|
//
|
||||||
|
// It should return nil if there is no Metadata
|
||||||
|
func (o *Object) Metadata(ctx context.Context) (fs.Metadata, error) {
|
||||||
|
do, ok := o.Object.(fs.Metadataer)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return do.Metadata(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
// About gets quota information from the Fs
|
// About gets quota information from the Fs
|
||||||
func (f *Fs) About(ctx context.Context) (*fs.Usage, error) {
|
func (f *Fs) About(ctx context.Context) (*fs.Usage, error) {
|
||||||
if atomic.LoadInt64(&f.cacheExpiry) <= time.Now().Unix() {
|
if atomic.LoadInt64(&f.cacheExpiry) <= time.Now().Unix() {
|
||||||
@ -363,3 +410,8 @@ func (f *Fs) updateUsageCore(lock bool) error {
|
|||||||
f.usage = usage
|
f.usage = usage
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check the interfaces are satisfied
|
||||||
|
var (
|
||||||
|
_ fs.FullObject = (*Object)(nil)
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user