mirror of
https://github.com/rclone/rclone.git
synced 2024-11-25 18:04:55 +01:00
fs: Add CanHaveEmptyDirectories and BucketBased feature flags to all remotes
This commit is contained in:
parent
c1bfdd893f
commit
20ae7d562b
@ -190,7 +190,11 @@ func NewFs(name, root string) (fs.Fs, error) {
|
|||||||
pacer: pacer.New().SetMinSleep(minSleep).SetPacer(pacer.AmazonCloudDrivePacer),
|
pacer: pacer.New().SetMinSleep(minSleep).SetPacer(pacer.AmazonCloudDrivePacer),
|
||||||
noAuthClient: fs.Config.Client(),
|
noAuthClient: fs.Config.Client(),
|
||||||
}
|
}
|
||||||
f.features = (&fs.Features{CaseInsensitive: true, ReadMimeType: true}).Fill(f)
|
f.features = (&fs.Features{
|
||||||
|
CaseInsensitive: true,
|
||||||
|
ReadMimeType: true,
|
||||||
|
CanHaveEmptyDirectories: true,
|
||||||
|
}).Fill(f)
|
||||||
|
|
||||||
// Renew the token in the background
|
// Renew the token in the background
|
||||||
f.tokenRenewer = oauthutil.NewRenew(f.String(), ts, func() error {
|
f.tokenRenewer = oauthutil.NewRenew(f.String(), ts, func() error {
|
||||||
|
@ -214,7 +214,11 @@ func NewFs(name, root string) (fs.Fs, error) {
|
|||||||
pacer: pacer.New().SetMinSleep(minSleep).SetMaxSleep(maxSleep).SetDecayConstant(decayConstant),
|
pacer: pacer.New().SetMinSleep(minSleep).SetMaxSleep(maxSleep).SetDecayConstant(decayConstant),
|
||||||
uploadToken: pacer.NewTokenDispenser(fs.Config.Transfers),
|
uploadToken: pacer.NewTokenDispenser(fs.Config.Transfers),
|
||||||
}
|
}
|
||||||
f.features = (&fs.Features{ReadMimeType: true, WriteMimeType: true}).Fill(f)
|
f.features = (&fs.Features{
|
||||||
|
ReadMimeType: true,
|
||||||
|
WriteMimeType: true,
|
||||||
|
BucketBased: true,
|
||||||
|
}).Fill(f)
|
||||||
if f.root != "" {
|
if f.root != "" {
|
||||||
f.root += "/"
|
f.root += "/"
|
||||||
// Check to see if the (container,directory) is actually an existing file
|
// Check to see if the (container,directory) is actually an existing file
|
||||||
|
6
b2/b2.go
6
b2/b2.go
@ -257,7 +257,11 @@ func NewFs(name, root string) (fs.Fs, error) {
|
|||||||
pacer: pacer.New().SetMinSleep(minSleep).SetMaxSleep(maxSleep).SetDecayConstant(decayConstant),
|
pacer: pacer.New().SetMinSleep(minSleep).SetMaxSleep(maxSleep).SetDecayConstant(decayConstant),
|
||||||
bufferTokens: make(chan []byte, fs.Config.Transfers),
|
bufferTokens: make(chan []byte, fs.Config.Transfers),
|
||||||
}
|
}
|
||||||
f.features = (&fs.Features{ReadMimeType: true, WriteMimeType: true}).Fill(f)
|
f.features = (&fs.Features{
|
||||||
|
ReadMimeType: true,
|
||||||
|
WriteMimeType: true,
|
||||||
|
BucketBased: true,
|
||||||
|
}).Fill(f)
|
||||||
// Set the test flag if required
|
// Set the test flag if required
|
||||||
if *b2TestMode != "" {
|
if *b2TestMode != "" {
|
||||||
testMode := strings.TrimSpace(*b2TestMode)
|
testMode := strings.TrimSpace(*b2TestMode)
|
||||||
|
@ -244,7 +244,10 @@ func NewFs(name, root string) (fs.Fs, error) {
|
|||||||
pacer: pacer.New().SetMinSleep(minSleep).SetMaxSleep(maxSleep).SetDecayConstant(decayConstant),
|
pacer: pacer.New().SetMinSleep(minSleep).SetMaxSleep(maxSleep).SetDecayConstant(decayConstant),
|
||||||
uploadToken: pacer.NewTokenDispenser(fs.Config.Transfers),
|
uploadToken: pacer.NewTokenDispenser(fs.Config.Transfers),
|
||||||
}
|
}
|
||||||
f.features = (&fs.Features{CaseInsensitive: true}).Fill(f)
|
f.features = (&fs.Features{
|
||||||
|
CaseInsensitive: true,
|
||||||
|
CanHaveEmptyDirectories: true,
|
||||||
|
}).Fill(f)
|
||||||
f.srv.SetErrorHandler(errorHandler)
|
f.srv.SetErrorHandler(errorHandler)
|
||||||
|
|
||||||
// Renew the token in the background
|
// Renew the token in the background
|
||||||
|
@ -108,6 +108,8 @@ func NewFs(name, rpath string) (fs.Fs, error) {
|
|||||||
DuplicateFiles: true,
|
DuplicateFiles: true,
|
||||||
ReadMimeType: false, // MimeTypes not supported with crypt
|
ReadMimeType: false, // MimeTypes not supported with crypt
|
||||||
WriteMimeType: false,
|
WriteMimeType: false,
|
||||||
|
BucketBased: true,
|
||||||
|
CanHaveEmptyDirectories: true,
|
||||||
}).Fill(f).Mask(wrappedFs)
|
}).Fill(f).Mask(wrappedFs)
|
||||||
return f, err
|
return f, err
|
||||||
}
|
}
|
||||||
|
@ -408,7 +408,12 @@ func NewFs(name, path string) (fs.Fs, error) {
|
|||||||
}
|
}
|
||||||
f.teamDriveID = fs.ConfigFileGet(name, "team_drive")
|
f.teamDriveID = fs.ConfigFileGet(name, "team_drive")
|
||||||
f.isTeamDrive = f.teamDriveID != ""
|
f.isTeamDrive = f.teamDriveID != ""
|
||||||
f.features = (&fs.Features{DuplicateFiles: true, ReadMimeType: true, WriteMimeType: true}).Fill(f)
|
f.features = (&fs.Features{
|
||||||
|
DuplicateFiles: true,
|
||||||
|
ReadMimeType: true,
|
||||||
|
WriteMimeType: true,
|
||||||
|
CanHaveEmptyDirectories: true,
|
||||||
|
}).Fill(f)
|
||||||
|
|
||||||
// Create a new authorized Drive client.
|
// Create a new authorized Drive client.
|
||||||
f.client = oAuthClient
|
f.client = oAuthClient
|
||||||
|
@ -185,7 +185,11 @@ func NewFs(name, root string) (fs.Fs, error) {
|
|||||||
srv: srv,
|
srv: srv,
|
||||||
pacer: pacer.New().SetMinSleep(minSleep).SetMaxSleep(maxSleep).SetDecayConstant(decayConstant),
|
pacer: pacer.New().SetMinSleep(minSleep).SetMaxSleep(maxSleep).SetDecayConstant(decayConstant),
|
||||||
}
|
}
|
||||||
f.features = (&fs.Features{CaseInsensitive: true, ReadMimeType: true}).Fill(f)
|
f.features = (&fs.Features{
|
||||||
|
CaseInsensitive: true,
|
||||||
|
ReadMimeType: true,
|
||||||
|
CanHaveEmptyDirectories: true,
|
||||||
|
}).Fill(f)
|
||||||
f.setRoot(root)
|
f.setRoot(root)
|
||||||
|
|
||||||
// See if the root is actually an object
|
// See if the root is actually an object
|
||||||
|
14
fs/fs.go
14
fs/fs.go
@ -245,11 +245,13 @@ type ListRFn func(dir string, callback ListRCallback) error
|
|||||||
|
|
||||||
// Features describe the optional features of the Fs
|
// Features describe the optional features of the Fs
|
||||||
type Features struct {
|
type Features struct {
|
||||||
// Feature flags
|
// Feature flags, whether Fs
|
||||||
CaseInsensitive bool
|
CaseInsensitive bool // has case insensitive files
|
||||||
DuplicateFiles bool
|
DuplicateFiles bool // allows duplicate files
|
||||||
ReadMimeType bool
|
ReadMimeType bool // can read the mime type of objects
|
||||||
WriteMimeType bool
|
WriteMimeType bool // can set the mime type of objects
|
||||||
|
CanHaveEmptyDirectories bool // can have empty directories
|
||||||
|
BucketBased bool // is bucket based (like s3, swift etc)
|
||||||
|
|
||||||
// Purge all files in the root and the root directory
|
// Purge all files in the root and the root directory
|
||||||
//
|
//
|
||||||
@ -444,6 +446,8 @@ func (ft *Features) Mask(f Fs) *Features {
|
|||||||
ft.DuplicateFiles = ft.DuplicateFiles && mask.DuplicateFiles
|
ft.DuplicateFiles = ft.DuplicateFiles && mask.DuplicateFiles
|
||||||
ft.ReadMimeType = ft.ReadMimeType && mask.ReadMimeType
|
ft.ReadMimeType = ft.ReadMimeType && mask.ReadMimeType
|
||||||
ft.WriteMimeType = ft.WriteMimeType && mask.WriteMimeType
|
ft.WriteMimeType = ft.WriteMimeType && mask.WriteMimeType
|
||||||
|
ft.CanHaveEmptyDirectories = ft.CanHaveEmptyDirectories && mask.CanHaveEmptyDirectories
|
||||||
|
ft.BucketBased = ft.BucketBased && mask.BucketBased
|
||||||
if mask.Purge == nil {
|
if mask.Purge == nil {
|
||||||
ft.Purge = nil
|
ft.Purge = nil
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,9 @@ func NewFs(name, root string) (ff fs.Fs, err error) {
|
|||||||
pass: pass,
|
pass: pass,
|
||||||
dialAddr: dialAddr,
|
dialAddr: dialAddr,
|
||||||
}
|
}
|
||||||
f.features = (&fs.Features{}).Fill(f)
|
f.features = (&fs.Features{
|
||||||
|
CanHaveEmptyDirectories: true,
|
||||||
|
}).Fill(f)
|
||||||
// Make a connection and pool it to return errors early
|
// Make a connection and pool it to return errors early
|
||||||
c, err := f.getFtpConnection()
|
c, err := f.getFtpConnection()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -317,7 +317,11 @@ func NewFs(name, root string) (fs.Fs, error) {
|
|||||||
location: fs.ConfigFileGet(name, "location"),
|
location: fs.ConfigFileGet(name, "location"),
|
||||||
storageClass: fs.ConfigFileGet(name, "storage_class"),
|
storageClass: fs.ConfigFileGet(name, "storage_class"),
|
||||||
}
|
}
|
||||||
f.features = (&fs.Features{ReadMimeType: true, WriteMimeType: true}).Fill(f)
|
f.features = (&fs.Features{
|
||||||
|
ReadMimeType: true,
|
||||||
|
WriteMimeType: true,
|
||||||
|
BucketBased: true,
|
||||||
|
}).Fill(f)
|
||||||
if f.objectACL == "" {
|
if f.objectACL == "" {
|
||||||
f.objectACL = "private"
|
f.objectACL = "private"
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,9 @@ func NewFs(name, root string) (fs.Fs, error) {
|
|||||||
endpoint: u,
|
endpoint: u,
|
||||||
endpointURL: u.String(),
|
endpointURL: u.String(),
|
||||||
}
|
}
|
||||||
f.features = (&fs.Features{}).Fill(f)
|
f.features = (&fs.Features{
|
||||||
|
CanHaveEmptyDirectories: true,
|
||||||
|
}).Fill(f)
|
||||||
if isFile {
|
if isFile {
|
||||||
return f, fs.ErrorIsFile
|
return f, fs.ErrorIsFile
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,10 @@ func NewFs(name, root string) (fs.Fs, error) {
|
|||||||
dirNames: newMapper(),
|
dirNames: newMapper(),
|
||||||
}
|
}
|
||||||
f.root = f.cleanPath(root)
|
f.root = f.cleanPath(root)
|
||||||
f.features = (&fs.Features{CaseInsensitive: f.caseInsensitive()}).Fill(f)
|
f.features = (&fs.Features{
|
||||||
|
CaseInsensitive: f.caseInsensitive(),
|
||||||
|
CanHaveEmptyDirectories: true,
|
||||||
|
}).Fill(f)
|
||||||
if *followSymlinks {
|
if *followSymlinks {
|
||||||
f.lstat = os.Stat
|
f.lstat = os.Stat
|
||||||
}
|
}
|
||||||
|
@ -205,7 +205,11 @@ func NewFs(name, root string) (fs.Fs, error) {
|
|||||||
srv: rest.NewClient(oAuthClient).SetRoot(rootURL),
|
srv: rest.NewClient(oAuthClient).SetRoot(rootURL),
|
||||||
pacer: pacer.New().SetMinSleep(minSleep).SetMaxSleep(maxSleep).SetDecayConstant(decayConstant),
|
pacer: pacer.New().SetMinSleep(minSleep).SetMaxSleep(maxSleep).SetDecayConstant(decayConstant),
|
||||||
}
|
}
|
||||||
f.features = (&fs.Features{CaseInsensitive: true, ReadMimeType: true}).Fill(f)
|
f.features = (&fs.Features{
|
||||||
|
CaseInsensitive: true,
|
||||||
|
ReadMimeType: true,
|
||||||
|
CanHaveEmptyDirectories: true,
|
||||||
|
}).Fill(f)
|
||||||
f.srv.SetErrorHandler(errorHandler)
|
f.srv.SetErrorHandler(errorHandler)
|
||||||
|
|
||||||
// Renew the token in the background
|
// Renew the token in the background
|
||||||
|
@ -240,7 +240,11 @@ func NewFs(name, root string) (fs.Fs, error) {
|
|||||||
bucket: bucket,
|
bucket: bucket,
|
||||||
svc: svc,
|
svc: svc,
|
||||||
}
|
}
|
||||||
f.features = (&fs.Features{ReadMimeType: true, WriteMimeType: true}).Fill(f)
|
f.features = (&fs.Features{
|
||||||
|
ReadMimeType: true,
|
||||||
|
WriteMimeType: true,
|
||||||
|
BucketBased: true,
|
||||||
|
}).Fill(f)
|
||||||
|
|
||||||
if f.root != "" {
|
if f.root != "" {
|
||||||
if !strings.HasSuffix(f.root, "/") {
|
if !strings.HasSuffix(f.root, "/") {
|
||||||
|
6
s3/s3.go
6
s3/s3.go
@ -401,7 +401,11 @@ func NewFs(name, root string) (fs.Fs, error) {
|
|||||||
sse: fs.ConfigFileGet(name, "server_side_encryption"),
|
sse: fs.ConfigFileGet(name, "server_side_encryption"),
|
||||||
storageClass: fs.ConfigFileGet(name, "storage_class"),
|
storageClass: fs.ConfigFileGet(name, "storage_class"),
|
||||||
}
|
}
|
||||||
f.features = (&fs.Features{ReadMimeType: true, WriteMimeType: true}).Fill(f)
|
f.features = (&fs.Features{
|
||||||
|
ReadMimeType: true,
|
||||||
|
WriteMimeType: true,
|
||||||
|
BucketBased: true,
|
||||||
|
}).Fill(f)
|
||||||
if *s3ACL != "" {
|
if *s3ACL != "" {
|
||||||
f.acl = *s3ACL
|
f.acl = *s3ACL
|
||||||
}
|
}
|
||||||
|
@ -290,7 +290,9 @@ func NewFs(name, root string) (fs.Fs, error) {
|
|||||||
mkdirLock: newStringLock(),
|
mkdirLock: newStringLock(),
|
||||||
connLimit: rate.NewLimiter(rate.Limit(connectionsPerSecond), 1),
|
connLimit: rate.NewLimiter(rate.Limit(connectionsPerSecond), 1),
|
||||||
}
|
}
|
||||||
f.features = (&fs.Features{}).Fill(f)
|
f.features = (&fs.Features{
|
||||||
|
CanHaveEmptyDirectories: true,
|
||||||
|
}).Fill(f)
|
||||||
// Make a connection and pool it to return errors early
|
// Make a connection and pool it to return errors early
|
||||||
c, err := f.getSftpConnection()
|
c, err := f.getSftpConnection()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -200,7 +200,11 @@ func NewFsWithConnection(name, root string, c *swift.Connection) (fs.Fs, error)
|
|||||||
segmentsContainer: container + "_segments",
|
segmentsContainer: container + "_segments",
|
||||||
root: directory,
|
root: directory,
|
||||||
}
|
}
|
||||||
f.features = (&fs.Features{ReadMimeType: true, WriteMimeType: true}).Fill(f)
|
f.features = (&fs.Features{
|
||||||
|
ReadMimeType: true,
|
||||||
|
WriteMimeType: true,
|
||||||
|
BucketBased: true,
|
||||||
|
}).Fill(f)
|
||||||
// StorageURL overloading
|
// StorageURL overloading
|
||||||
storageURL := fs.ConfigFileGet(name, "storage_url")
|
storageURL := fs.ConfigFileGet(name, "storage_url")
|
||||||
if storageURL != "" {
|
if storageURL != "" {
|
||||||
|
@ -133,7 +133,11 @@ func NewFs(name, root string) (fs.Fs, error) {
|
|||||||
name: name,
|
name: name,
|
||||||
yd: yandexDisk,
|
yd: yandexDisk,
|
||||||
}
|
}
|
||||||
f.features = (&fs.Features{ReadMimeType: true, WriteMimeType: true}).Fill(f)
|
f.features = (&fs.Features{
|
||||||
|
ReadMimeType: true,
|
||||||
|
WriteMimeType: true,
|
||||||
|
CanHaveEmptyDirectories: true,
|
||||||
|
}).Fill(f)
|
||||||
f.setRoot(root)
|
f.setRoot(root)
|
||||||
|
|
||||||
// Check to see if the object exists and is a file
|
// Check to see if the object exists and is a file
|
||||||
|
Loading…
Reference in New Issue
Block a user