mirror of
https://github.com/rclone/rclone.git
synced 2024-11-07 09:04:52 +01:00
fs: add Directory Metadata flags for backends and interfaces
Add backend flags - ReadDirMetadata - WriteDirMetadata - WriteDirSetModTime - UserDirMetadata - DirModTimeUpdatesOnWrite Add Metadata/SetMetadata for directories. Add MkdirMetadata optional feature
This commit is contained in:
parent
6da52d76a7
commit
a4cadd1128
@ -29,6 +29,11 @@ type Features struct {
|
|||||||
ReadMetadata bool // can read metadata from objects
|
ReadMetadata bool // can read metadata from objects
|
||||||
WriteMetadata bool // can write metadata to objects
|
WriteMetadata bool // can write metadata to objects
|
||||||
UserMetadata bool // can read/write general purpose metadata
|
UserMetadata bool // can read/write general purpose metadata
|
||||||
|
ReadDirMetadata bool // can read metadata from directories (implements Directory.Metadata)
|
||||||
|
WriteDirMetadata bool // can write metadata to directories (implements Directory.SetMetadata)
|
||||||
|
WriteDirSetModTime bool // can write metadata to directories (implements Directory.SetModTime)
|
||||||
|
UserDirMetadata bool // can read/write general purpose metadata to/from directories
|
||||||
|
DirModTimeUpdatesOnWrite bool // indicate writing files to a directory updates its modtime
|
||||||
FilterAware bool // can make use of filters if provided for listing
|
FilterAware bool // can make use of filters if provided for listing
|
||||||
PartialUploads bool // uploaded file can appear incomplete on the fs while it's being uploaded
|
PartialUploads bool // uploaded file can appear incomplete on the fs while it's being uploaded
|
||||||
NoMultiThreading bool // set if can't have multiplethreads on one download open
|
NoMultiThreading bool // set if can't have multiplethreads on one download open
|
||||||
@ -75,6 +80,15 @@ type Features struct {
|
|||||||
// If destination exists then return fs.ErrorDirExists
|
// If destination exists then return fs.ErrorDirExists
|
||||||
DirMove func(ctx context.Context, src Fs, srcRemote, dstRemote string) error
|
DirMove func(ctx context.Context, src Fs, srcRemote, dstRemote string) error
|
||||||
|
|
||||||
|
// MkdirMetadata makes the directory passed in as dir.
|
||||||
|
//
|
||||||
|
// It shouldn't return an error if it already exists.
|
||||||
|
//
|
||||||
|
// If the metadata is not nil it is set.
|
||||||
|
//
|
||||||
|
// It returns the directory that was created.
|
||||||
|
MkdirMetadata func(ctx context.Context, dir string, metadata Metadata) (Directory, error)
|
||||||
|
|
||||||
// ChangeNotify calls the passed function with a path
|
// ChangeNotify calls the passed function with a path
|
||||||
// that has had changes. If the implementation
|
// that has had changes. If the implementation
|
||||||
// uses polling, it should adhere to the given interval.
|
// uses polling, it should adhere to the given interval.
|
||||||
@ -274,6 +288,9 @@ func (ft *Features) Fill(ctx context.Context, f Fs) *Features {
|
|||||||
if do, ok := f.(DirMover); ok {
|
if do, ok := f.(DirMover); ok {
|
||||||
ft.DirMove = do.DirMove
|
ft.DirMove = do.DirMove
|
||||||
}
|
}
|
||||||
|
if do, ok := f.(MkdirMetadataer); ok {
|
||||||
|
ft.MkdirMetadata = do.MkdirMetadata
|
||||||
|
}
|
||||||
if do, ok := f.(ChangeNotifier); ok {
|
if do, ok := f.(ChangeNotifier); ok {
|
||||||
ft.ChangeNotify = do.ChangeNotify
|
ft.ChangeNotify = do.ChangeNotify
|
||||||
}
|
}
|
||||||
@ -348,6 +365,11 @@ func (ft *Features) Mask(ctx context.Context, f Fs) *Features {
|
|||||||
ft.ReadMetadata = ft.ReadMetadata && mask.ReadMetadata
|
ft.ReadMetadata = ft.ReadMetadata && mask.ReadMetadata
|
||||||
ft.WriteMetadata = ft.WriteMetadata && mask.WriteMetadata
|
ft.WriteMetadata = ft.WriteMetadata && mask.WriteMetadata
|
||||||
ft.UserMetadata = ft.UserMetadata && mask.UserMetadata
|
ft.UserMetadata = ft.UserMetadata && mask.UserMetadata
|
||||||
|
ft.ReadDirMetadata = ft.ReadDirMetadata && mask.ReadDirMetadata
|
||||||
|
ft.WriteDirMetadata = ft.WriteDirMetadata && mask.WriteDirMetadata
|
||||||
|
ft.WriteDirSetModTime = ft.WriteDirSetModTime && mask.WriteDirSetModTime
|
||||||
|
ft.UserDirMetadata = ft.UserDirMetadata && mask.UserDirMetadata
|
||||||
|
ft.DirModTimeUpdatesOnWrite = ft.DirModTimeUpdatesOnWrite && mask.DirModTimeUpdatesOnWrite
|
||||||
ft.CanHaveEmptyDirectories = ft.CanHaveEmptyDirectories && mask.CanHaveEmptyDirectories
|
ft.CanHaveEmptyDirectories = ft.CanHaveEmptyDirectories && mask.CanHaveEmptyDirectories
|
||||||
ft.BucketBased = ft.BucketBased && mask.BucketBased
|
ft.BucketBased = ft.BucketBased && mask.BucketBased
|
||||||
ft.BucketBasedRootOK = ft.BucketBasedRootOK && mask.BucketBasedRootOK
|
ft.BucketBasedRootOK = ft.BucketBasedRootOK && mask.BucketBasedRootOK
|
||||||
@ -374,6 +396,9 @@ func (ft *Features) Mask(ctx context.Context, f Fs) *Features {
|
|||||||
if mask.DirMove == nil {
|
if mask.DirMove == nil {
|
||||||
ft.DirMove = nil
|
ft.DirMove = nil
|
||||||
}
|
}
|
||||||
|
if mask.MkdirMetadata == nil {
|
||||||
|
ft.MkdirMetadata = nil
|
||||||
|
}
|
||||||
if mask.ChangeNotify == nil {
|
if mask.ChangeNotify == nil {
|
||||||
ft.ChangeNotify = nil
|
ft.ChangeNotify = nil
|
||||||
}
|
}
|
||||||
@ -505,6 +530,18 @@ type DirMover interface {
|
|||||||
DirMove(ctx context.Context, src Fs, srcRemote, dstRemote string) error
|
DirMove(ctx context.Context, src Fs, srcRemote, dstRemote string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MkdirMetadataer is an optional interface for Fs
|
||||||
|
type MkdirMetadataer interface {
|
||||||
|
// MkdirMetadata makes the directory passed in as dir.
|
||||||
|
//
|
||||||
|
// It shouldn't return an error if it already exists.
|
||||||
|
//
|
||||||
|
// If the metadata is not nil it is set.
|
||||||
|
//
|
||||||
|
// It returns the directory that was created.
|
||||||
|
MkdirMetadata(ctx context.Context, dir string, metadata Metadata) (Directory, error)
|
||||||
|
}
|
||||||
|
|
||||||
// ChangeNotifier is an optional interface for Fs
|
// ChangeNotifier is an optional interface for Fs
|
||||||
type ChangeNotifier interface {
|
type ChangeNotifier interface {
|
||||||
// ChangeNotify calls the passed function with a path
|
// ChangeNotify calls the passed function with a path
|
||||||
|
55
fs/types.go
55
fs/types.go
@ -144,6 +144,16 @@ type Directory interface {
|
|||||||
ID() string
|
ID() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FullDirectory contains all the optional interfaces for Directory
|
||||||
|
//
|
||||||
|
// Use for checking making wrapping Directories implement everything
|
||||||
|
type FullDirectory interface {
|
||||||
|
Directory
|
||||||
|
Metadataer
|
||||||
|
SetMetadataer
|
||||||
|
SetModTimer
|
||||||
|
}
|
||||||
|
|
||||||
// MimeTyper is an optional interface for Object
|
// MimeTyper is an optional interface for Object
|
||||||
type MimeTyper interface {
|
type MimeTyper interface {
|
||||||
// MimeType returns the content type of the Object if
|
// MimeType returns the content type of the Object if
|
||||||
@ -183,14 +193,32 @@ type GetTierer interface {
|
|||||||
GetTier() string
|
GetTier() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Metadataer is an optional interface for Object
|
// Metadataer is an optional interface for DirEntry
|
||||||
type Metadataer interface {
|
type Metadataer interface {
|
||||||
// Metadata returns metadata for an object
|
// Metadata returns metadata for an DirEntry
|
||||||
//
|
//
|
||||||
// It should return nil if there is no Metadata
|
// It should return nil if there is no Metadata
|
||||||
Metadata(ctx context.Context) (Metadata, error)
|
Metadata(ctx context.Context) (Metadata, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetMetadataer is an optional interface for DirEntry
|
||||||
|
type SetMetadataer interface {
|
||||||
|
// SetMetadata sets metadata for an DirEntry
|
||||||
|
//
|
||||||
|
// It should return fs.ErrorNotImplemented if it can't set metadata
|
||||||
|
SetMetadata(ctx context.Context, metadata Metadata) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetModTimer is an optional interface for Directory.
|
||||||
|
//
|
||||||
|
// Object implements this as part of its requires set of interfaces.
|
||||||
|
type SetModTimer interface {
|
||||||
|
// SetModTime sets the metadata on the DirEntry to set the modification date
|
||||||
|
//
|
||||||
|
// If there is any other metadata it does not overwrite it.
|
||||||
|
SetModTime(ctx context.Context, t time.Time) error
|
||||||
|
}
|
||||||
|
|
||||||
// FullObjectInfo contains all the read-only optional interfaces
|
// FullObjectInfo contains all the read-only optional interfaces
|
||||||
//
|
//
|
||||||
// Use for checking making wrapping ObjectInfos implement everything
|
// Use for checking making wrapping ObjectInfos implement everything
|
||||||
@ -248,6 +276,29 @@ func ObjectOptionalInterfaces(o Object) (supported, unsupported []string) {
|
|||||||
return supported, unsupported
|
return supported, unsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DirectoryOptionalInterfaces returns the names of supported and
|
||||||
|
// unsupported optional interfaces for a Directory
|
||||||
|
func DirectoryOptionalInterfaces(d Directory) (supported, unsupported []string) {
|
||||||
|
store := func(ok bool, name string) {
|
||||||
|
if ok {
|
||||||
|
supported = append(supported, name)
|
||||||
|
} else {
|
||||||
|
unsupported = append(unsupported, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := d.(Metadataer)
|
||||||
|
store(ok, "Metadata")
|
||||||
|
|
||||||
|
_, ok = d.(SetMetadataer)
|
||||||
|
store(ok, "SetMetadata")
|
||||||
|
|
||||||
|
_, ok = d.(SetModTimer)
|
||||||
|
store(ok, "SetModTime")
|
||||||
|
|
||||||
|
return supported, unsupported
|
||||||
|
}
|
||||||
|
|
||||||
// ListRCallback defines a callback function for ListR to use
|
// ListRCallback defines a callback function for ListR to use
|
||||||
//
|
//
|
||||||
// It is called for each tranche of entries read from the listing and
|
// It is called for each tranche of entries read from the listing and
|
||||||
|
Loading…
Reference in New Issue
Block a user