mirror of
https://github.com/rclone/rclone.git
synced 2025-12-11 22:14:05 +01:00
s3: empty directory markers - #3453
This commit is contained in:
committed by
Nick Craig-Wood
parent
aca7d0fd22
commit
b6a95c70e9
@@ -2196,6 +2196,15 @@ See: https://github.com/rclone/rclone/issues/4673, https://github.com/rclone/rcl
|
||||
This is usually set to a CloudFront CDN URL as AWS S3 offers
|
||||
cheaper egress for data downloaded through the CloudFront network.`,
|
||||
Advanced: true,
|
||||
}, {
|
||||
Name: "directory_markers",
|
||||
Default: false,
|
||||
Advanced: true,
|
||||
Help: `Upload an empty object with a trailing slash in name when new directory is created
|
||||
|
||||
Empty folders are unsupported for bucket based remotes, this option creates an empty
|
||||
object named "/", to persist folder.
|
||||
`,
|
||||
}, {
|
||||
Name: "use_multipart_etag",
|
||||
Help: `Whether to use ETag in multipart uploads for verification
|
||||
@@ -2425,6 +2434,7 @@ type Options struct {
|
||||
MemoryPoolUseMmap bool `config:"memory_pool_use_mmap"`
|
||||
DisableHTTP2 bool `config:"disable_http2"`
|
||||
DownloadURL string `config:"download_url"`
|
||||
DirectoryMarkers bool `config:"directory_markers"`
|
||||
UseMultipartEtag fs.Tristate `config:"use_multipart_etag"`
|
||||
UsePresignedRequest bool `config:"use_presigned_request"`
|
||||
Versions bool `config:"versions"`
|
||||
@@ -3879,7 +3889,27 @@ func (f *Fs) bucketExists(ctx context.Context, bucket string) (bool, error) {
|
||||
// Mkdir creates the bucket if it doesn't exist
|
||||
func (f *Fs) Mkdir(ctx context.Context, dir string) error {
|
||||
bucket, _ := f.split(dir)
|
||||
return f.makeBucket(ctx, bucket)
|
||||
e := f.makeBucket(ctx, bucket)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
// Create directory marker file
|
||||
if f.opt.DirectoryMarkers && bucket != "" && dir != "" {
|
||||
markerFilePath := fmt.Sprintf("%s/", dir)
|
||||
markerFileContent := io.Reader(strings.NewReader(""))
|
||||
markerFileObject := &Object{
|
||||
fs: f,
|
||||
remote: markerFilePath,
|
||||
meta: map[string]string{
|
||||
metaMtime: swift.TimeToFloatString(time.Now()),
|
||||
},
|
||||
}
|
||||
_, e := f.Put(ctx, markerFileContent, markerFileObject)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// makeBucket creates the bucket if it doesn't exist
|
||||
@@ -3920,6 +3950,15 @@ func (f *Fs) makeBucket(ctx context.Context, bucket string) error {
|
||||
// Returns an error if it isn't empty
|
||||
func (f *Fs) Rmdir(ctx context.Context, dir string) error {
|
||||
bucket, directory := f.split(dir)
|
||||
// Remove directory marker file
|
||||
if f.opt.DirectoryMarkers && bucket != "" && dir != "" {
|
||||
markerFilePath := fmt.Sprintf("%s/", dir)
|
||||
markerFileObject := &Object{
|
||||
fs: f,
|
||||
remote: markerFilePath,
|
||||
}
|
||||
_ = markerFileObject.Remove(ctx)
|
||||
}
|
||||
if bucket == "" || directory != "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user