Skip to content

Commit 87b7add

Browse files
committed
fix(chunker): EncodeUnicodeBMP on chunker
1 parent df4a33b commit 87b7add

3 files changed

Lines changed: 33 additions & 0 deletions

File tree

backend/box/box.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,11 @@ func (f *Fs) Features() *fs.Features {
356356
return f.features
357357
}
358358

359+
// Encoder returns the encoder for this Fs
360+
func (f *Fs) Encoder() encoder.Encoder {
361+
return f.opt.Enc
362+
}
363+
359364
// parsePath parses a box 'url'
360365
func parsePath(path string) (root string) {
361366
root = strings.Trim(path, "/")

backend/chunker/chunker.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ import (
7878
// Metadata format v1 does not define any control chunk types,
7979
// they are currently ignored aka reserved.
8080
// In future they can be used to implement resumable uploads etc.
81+
// Encoderer is an optional interface for Fs to return its encoder.
82+
// This is used to handle backends that encode file names in a way that
83+
// might cause issues with chunker's file name matching (e.g., EncodeUnicodeBMP).
84+
type Encoderer interface {
85+
Encoder() encoder.Encoder
86+
}
87+
8188
const (
8289
ctrlTypeRegStr = `[a-z][a-z0-9]{2,6}`
8390
tempSuffixFormat = `_%04s`
@@ -2552,6 +2559,16 @@ func (f *Fs) Features() *fs.Features {
25522559
return f.features
25532560
}
25542561

2562+
func (f *Fs) Encoder() encoder.Encoder {
2563+
var baseEncoder encoder.Encoder
2564+
if do, ok := f.base.(Encoderer); ok {
2565+
baseEncoder = do.Encoder()
2566+
} else {
2567+
baseEncoder = encoder.Identity()
2568+
}
2569+
return baseEncoder
2570+
}
2571+
25552572
// String returns a description of the FS
25562573
func (f *Fs) String() string {
25572574
return fmt.Sprintf("Chunked '%s:%s'", f.name, f.root)

fs/march/march.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/rclone/rclone/fs/filter"
1616
"github.com/rclone/rclone/fs/list"
1717
"github.com/rclone/rclone/fs/walk"
18+
"github.com/rclone/rclone/lib/encoder"
1819
"github.com/rclone/rclone/lib/transform"
1920
"golang.org/x/text/unicode/norm"
2021
)
@@ -80,6 +81,10 @@ func (m *March) init(ctx context.Context) {
8081
}
8182
}
8283

84+
type Encoderer interface {
85+
Encoder() encoder.Encoder
86+
}
87+
8388
// srcOrDstKey turns a directory entry into a sort key using the defined transforms.
8489
func (m *March) srcOrDstKey(entry fs.DirEntry, isSrc bool) string {
8590
if entry == nil {
@@ -89,6 +94,12 @@ func (m *March) srcOrDstKey(entry fs.DirEntry, isSrc bool) string {
8994
_, isDirectory := entry.(fs.Directory)
9095
if isSrc {
9196
name = transform.Path(m.Ctx, name, isDirectory)
97+
// Encode src name using dst Fs encoder to normalize for comparison
98+
// Interface check for backends that encode filenames (e.g., Box with EncodeUnicodeBMP)
99+
if enc, ok := m.Fdst.(Encoderer); ok {
100+
encoder := enc.Encoder()
101+
name = encoder.ToStandardPath(encoder.FromStandardPath(name))
102+
}
92103
}
93104
for _, transform := range m.transforms {
94105
name = transform(name)

0 commit comments

Comments
 (0)