azureblob: ignore directory markers in inital Fs creation too - fixes #2806
This is a follow-up to feea0532
including the initial Fs creation
where the backend detects whether the path is pointing to a file or a
directory.
This commit is contained in:
parent
2d01a65e36
commit
733b072d4f
1 changed files with 44 additions and 25 deletions
|
@ -417,8 +417,8 @@ func NewFs(name, root string, m configmap.Mapper) (fs.Fs, error) {
|
||||||
}
|
}
|
||||||
_, err := f.NewObject(remote)
|
_, err := f.NewObject(remote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == fs.ErrorObjectNotFound {
|
if err == fs.ErrorObjectNotFound || err == fs.ErrorNotAFile {
|
||||||
// File doesn't exist so return old f
|
// File doesn't exist or is a directory so return old f
|
||||||
f.root = oldRoot
|
f.root = oldRoot
|
||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
@ -474,6 +474,21 @@ func (o *Object) updateMetadataWithModTime(modTime time.Time) {
|
||||||
o.meta[modTimeKey] = modTime.Format(timeFormatOut)
|
o.meta[modTimeKey] = modTime.Format(timeFormatOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns whether file is a directory marker or not
|
||||||
|
func isDirectoryMarker(size int64, metadata azblob.Metadata, remote string) bool {
|
||||||
|
// Directory markers are 0 length
|
||||||
|
if size == 0 {
|
||||||
|
// Note that metadata with hdi_isfolder = true seems to be a
|
||||||
|
// defacto standard for marking blobs as directories.
|
||||||
|
endsWithSlash := strings.HasSuffix(remote, "/")
|
||||||
|
if endsWithSlash || remote == "" || metadata["hdi_isfolder"] == "true" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// listFn is called from list to handle an object
|
// listFn is called from list to handle an object
|
||||||
type listFn func(remote string, object *azblob.BlobItem, isDirectory bool) error
|
type listFn func(remote string, object *azblob.BlobItem, isDirectory bool) error
|
||||||
|
|
||||||
|
@ -539,13 +554,8 @@ func (f *Fs) list(dir string, recurse bool, maxResults uint, fn listFn) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
remote := file.Name[len(f.root):]
|
remote := file.Name[len(f.root):]
|
||||||
// is this a directory marker?
|
if isDirectoryMarker(*file.Properties.ContentLength, file.Metadata, remote) {
|
||||||
if *file.Properties.ContentLength == 0 {
|
if strings.HasSuffix(remote, "/") {
|
||||||
// Note that metadata with hdi_isfolder = true seems to be a
|
|
||||||
// defacto standard for marking blobs as directories.
|
|
||||||
endsWithSlash := strings.HasSuffix(remote, "/")
|
|
||||||
if endsWithSlash || remote == "" || file.Metadata["hdi_isfolder"] == "true" {
|
|
||||||
if endsWithSlash {
|
|
||||||
remote = remote[:len(remote)-1]
|
remote = remote[:len(remote)-1]
|
||||||
}
|
}
|
||||||
err = fn(remote, file, true)
|
err = fn(remote, file, true)
|
||||||
|
@ -559,7 +569,6 @@ func (f *Fs) list(dir string, recurse bool, maxResults uint, fn listFn) error {
|
||||||
}
|
}
|
||||||
continue // skip directory marker
|
continue // skip directory marker
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Send object
|
// Send object
|
||||||
err = fn(remote, file, false)
|
err = fn(remote, file, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -981,27 +990,37 @@ func (o *Object) setMetadata(metadata azblob.Metadata) {
|
||||||
// o.md5
|
// o.md5
|
||||||
// o.meta
|
// o.meta
|
||||||
func (o *Object) decodeMetaDataFromPropertiesResponse(info *azblob.BlobGetPropertiesResponse) (err error) {
|
func (o *Object) decodeMetaDataFromPropertiesResponse(info *azblob.BlobGetPropertiesResponse) (err error) {
|
||||||
|
metadata := info.NewMetadata()
|
||||||
|
size := info.ContentLength()
|
||||||
|
if isDirectoryMarker(size, metadata, o.remote) {
|
||||||
|
return fs.ErrorNotAFile
|
||||||
|
}
|
||||||
// NOTE - Client library always returns MD5 as base64 decoded string, Object needs to maintain
|
// NOTE - Client library always returns MD5 as base64 decoded string, Object needs to maintain
|
||||||
// this as base64 encoded string.
|
// this as base64 encoded string.
|
||||||
o.md5 = base64.StdEncoding.EncodeToString(info.ContentMD5())
|
o.md5 = base64.StdEncoding.EncodeToString(info.ContentMD5())
|
||||||
o.mimeType = info.ContentType()
|
o.mimeType = info.ContentType()
|
||||||
o.size = info.ContentLength()
|
o.size = size
|
||||||
o.modTime = time.Time(info.LastModified())
|
o.modTime = time.Time(info.LastModified())
|
||||||
o.accessTier = azblob.AccessTierType(info.AccessTier())
|
o.accessTier = azblob.AccessTierType(info.AccessTier())
|
||||||
o.setMetadata(info.NewMetadata())
|
o.setMetadata(metadata)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Object) decodeMetaDataFromBlob(info *azblob.BlobItem) (err error) {
|
func (o *Object) decodeMetaDataFromBlob(info *azblob.BlobItem) (err error) {
|
||||||
|
metadata := info.Metadata
|
||||||
|
size := *info.Properties.ContentLength
|
||||||
|
if isDirectoryMarker(size, metadata, o.remote) {
|
||||||
|
return fs.ErrorNotAFile
|
||||||
|
}
|
||||||
// NOTE - Client library always returns MD5 as base64 decoded string, Object needs to maintain
|
// NOTE - Client library always returns MD5 as base64 decoded string, Object needs to maintain
|
||||||
// this as base64 encoded string.
|
// this as base64 encoded string.
|
||||||
o.md5 = base64.StdEncoding.EncodeToString(info.Properties.ContentMD5)
|
o.md5 = base64.StdEncoding.EncodeToString(info.Properties.ContentMD5)
|
||||||
o.mimeType = *info.Properties.ContentType
|
o.mimeType = *info.Properties.ContentType
|
||||||
o.size = *info.Properties.ContentLength
|
o.size = size
|
||||||
o.modTime = info.Properties.LastModified
|
o.modTime = info.Properties.LastModified
|
||||||
o.accessTier = info.Properties.AccessTier
|
o.accessTier = info.Properties.AccessTier
|
||||||
o.setMetadata(info.Metadata)
|
o.setMetadata(metadata)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue