swift: use lib/encoder

This commit is contained in:
Nick Craig-Wood 2019-09-21 11:47:59 +01:00
parent 3304bb7a56
commit 53bec33027
3 changed files with 33 additions and 9 deletions

View File

@ -17,6 +17,7 @@ import (
"github.com/rclone/rclone/fs" "github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/config/configmap" "github.com/rclone/rclone/fs/config/configmap"
"github.com/rclone/rclone/fs/config/configstruct" "github.com/rclone/rclone/fs/config/configstruct"
"github.com/rclone/rclone/fs/encodings"
"github.com/rclone/rclone/fs/fserrors" "github.com/rclone/rclone/fs/fserrors"
"github.com/rclone/rclone/fs/fshttp" "github.com/rclone/rclone/fs/fshttp"
"github.com/rclone/rclone/fs/hash" "github.com/rclone/rclone/fs/hash"
@ -60,6 +61,8 @@ copy operations.`,
Advanced: true, Advanced: true,
}} }}
const enc = encodings.Swift
// Register with Fs // Register with Fs
func init() { func init() {
fs.Register(&fs.RegInfo{ fs.Register(&fs.RegInfo{
@ -320,7 +323,8 @@ func parsePath(path string) (root string) {
// split returns container and containerPath from the rootRelativePath // split returns container and containerPath from the rootRelativePath
// relative to f.root // relative to f.root
func (f *Fs) split(rootRelativePath string) (container, containerPath string) { func (f *Fs) split(rootRelativePath string) (container, containerPath string) {
return bucket.Split(path.Join(f.root, rootRelativePath)) container, containerPath = bucket.Split(path.Join(f.root, rootRelativePath))
return enc.FromStandardName(container), enc.FromStandardPath(containerPath)
} }
// split returns container and containerPath from the object // split returns container and containerPath from the object
@ -441,9 +445,10 @@ func NewFsWithConnection(opt *Options, name, root string, c *swift.Connection, n
// Check to see if the object exists - ignoring directory markers // Check to see if the object exists - ignoring directory markers
var info swift.Object var info swift.Object
var err error var err error
encodedDirectory := enc.FromStandardPath(f.rootDirectory)
err = f.pacer.Call(func() (bool, error) { err = f.pacer.Call(func() (bool, error) {
var rxHeaders swift.Headers var rxHeaders swift.Headers
info, rxHeaders, err = f.c.Object(f.rootContainer, f.rootDirectory) info, rxHeaders, err = f.c.Object(f.rootContainer, encodedDirectory)
return shouldRetryHeaders(rxHeaders, err) return shouldRetryHeaders(rxHeaders, err)
}) })
if err == nil && info.ContentType != directoryMarkerContentType { if err == nil && info.ContentType != directoryMarkerContentType {
@ -553,17 +558,18 @@ func (f *Fs) listContainerRoot(container, directory, prefix string, addContainer
if !recurse { if !recurse {
isDirectory = strings.HasSuffix(object.Name, "/") isDirectory = strings.HasSuffix(object.Name, "/")
} }
if !strings.HasPrefix(object.Name, prefix) { remote := enc.ToStandardPath(object.Name)
fs.Logf(f, "Odd name received %q", object.Name) if !strings.HasPrefix(remote, prefix) {
fs.Logf(f, "Odd name received %q", remote)
continue continue
} }
if object.Name == prefix { if remote == prefix {
// If we have zero length directory markers ending in / then swift // If we have zero length directory markers ending in / then swift
// will return them in the listing for the directory which causes // will return them in the listing for the directory which causes
// duplicate directories. Ignore them here. // duplicate directories. Ignore them here.
continue continue
} }
remote := object.Name[len(prefix):] remote = remote[len(prefix):]
if addContainer { if addContainer {
remote = path.Join(container, remote) remote = path.Join(container, remote)
} }
@ -635,7 +641,7 @@ func (f *Fs) listContainers(ctx context.Context) (entries fs.DirEntries, err err
} }
for _, container := range containers { for _, container := range containers {
f.cache.MarkOK(container.Name) f.cache.MarkOK(container.Name)
d := fs.NewDir(container.Name, time.Time{}).SetSize(container.Bytes).SetItems(container.Count) d := fs.NewDir(enc.ToStandardName(container.Name), time.Time{}).SetSize(container.Bytes).SetItems(container.Count)
entries = append(entries, d) entries = append(entries, d)
} }
return entries, nil return entries, nil

View File

@ -472,6 +472,16 @@ ns.
This is a defacto standard (used in the official python-swiftclient This is a defacto standard (used in the official python-swiftclient
amongst others) for storing the modification time for an object. amongst others) for storing the modification time for an object.
### Restricted filename characters
| Character | Value | Replacement |
| --------- |:-----:|:-----------:|
| NUL | 0x00 | ␀ |
| / | 0x2F | |
Invalid UTF-8 bytes will also be [replaced](/overview/#invalid-utf8),
as they can't be used in JSON strings.
### Limitations ### ### Limitations ###
The Swift API doesn't return a correct MD5SUM for segmented files The Swift API doesn't return a correct MD5SUM for segmented files

View File

@ -257,6 +257,12 @@ const S3 = encoder.MultiEncoder(
encoder.EncodeSlash | encoder.EncodeSlash |
encoder.EncodeDot) encoder.EncodeDot)
// Swift is the encoding used by the swift backend
const Swift = encoder.MultiEncoder(
encoder.EncodeInvalidUtf8 |
encoder.EncodeSlash)
// ByName returns the encoder for a give backend name or nil // ByName returns the encoder for a give backend name or nil
func ByName(name string) encoder.Encoder { func ByName(name string) encoder.Encoder {
switch strings.ToLower(name) { switch strings.ToLower(name) {
@ -302,9 +308,11 @@ func ByName(name string) encoder.Encoder {
case "pcloud": case "pcloud":
return Pcloud return Pcloud
//case "qingstor": //case "qingstor":
//case "s3": case "s3":
return S3
//case "sftp": //case "sftp":
//case "swift": case "swift":
return Swift
//case "webdav": //case "webdav":
//case "yandex": //case "yandex":
default: default: