mirror of
https://github.com/rclone/rclone.git
synced 2025-07-20 13:52:05 +02:00
lib/transform adds the transform library, supporting advanced path name transformations for converting and renaming files and directories by applying prefixes, suffixes, and other alterations. It also adds the --name-transform flag for use with sync, copy, and move. Multiple transformations can be used in sequence, applied in the order they are specified on the command line. By default --name-transform will only apply to file names. The means only the leaf file name will be transformed. However some of the transforms would be better applied to the whole path or just directories. To choose which which part of the file path is affected some tags can be added to the --name-transform: file Only transform the leaf name of files (DEFAULT) dir Only transform name of directories - these may appear anywhere in the path all Transform the entire path for files and directories Example syntax: --name-transform file,prefix=ABC --name-transform dir,prefix=DEF
143 lines
4.5 KiB
Go
143 lines
4.5 KiB
Go
package transform
|
||
|
||
import (
|
||
"context"
|
||
"testing"
|
||
"time"
|
||
|
||
"github.com/stretchr/testify/assert"
|
||
"github.com/stretchr/testify/require"
|
||
)
|
||
|
||
// sync tests are in fs/sync/sync_transform_test.go to avoid import cycle issues
|
||
|
||
func newOptions(s ...string) (context.Context, error) {
|
||
ctx := context.Background()
|
||
err := SetOptions(ctx, s...)
|
||
return ctx, err
|
||
}
|
||
|
||
func TestPath(t *testing.T) {
|
||
for _, test := range []struct {
|
||
path string
|
||
want string
|
||
}{
|
||
{"", ""},
|
||
{"toe/toe/toe", "tictactoe/tictactoe/tictactoe"},
|
||
{"a/b/c", "tictaca/tictacb/tictacc"},
|
||
} {
|
||
ctx, err := newOptions("all,prefix=tac", "all,prefix=tic")
|
||
require.NoError(t, err)
|
||
|
||
got := Path(ctx, test.path, false)
|
||
assert.Equal(t, test.want, got)
|
||
}
|
||
}
|
||
|
||
func TestFileTagOnFile(t *testing.T) {
|
||
for _, test := range []struct {
|
||
path string
|
||
want string
|
||
}{
|
||
{"a/b/c.txt", "a/b/1c.txt"},
|
||
} {
|
||
ctx, err := newOptions("file,prefix=1")
|
||
require.NoError(t, err)
|
||
|
||
got := Path(ctx, test.path, false)
|
||
assert.Equal(t, test.want, got)
|
||
}
|
||
}
|
||
|
||
func TestDirTagOnFile(t *testing.T) {
|
||
for _, test := range []struct {
|
||
path string
|
||
want string
|
||
}{
|
||
{"a/b/c.txt", "1a/1b/c.txt"},
|
||
} {
|
||
ctx, err := newOptions("dir,prefix=1")
|
||
require.NoError(t, err)
|
||
|
||
got := Path(ctx, test.path, false)
|
||
assert.Equal(t, test.want, got)
|
||
}
|
||
}
|
||
|
||
func TestAllTag(t *testing.T) {
|
||
for _, test := range []struct {
|
||
path string
|
||
want string
|
||
}{
|
||
{"a/b/c.txt", "1a/1b/1c.txt"},
|
||
} {
|
||
ctx, err := newOptions("all,prefix=1")
|
||
require.NoError(t, err)
|
||
|
||
got := Path(ctx, test.path, false)
|
||
assert.Equal(t, test.want, got)
|
||
}
|
||
}
|
||
|
||
func TestFileTagOnDir(t *testing.T) {
|
||
for _, test := range []struct {
|
||
path string
|
||
want string
|
||
}{
|
||
{"a/b", "a/b"},
|
||
} {
|
||
ctx, err := newOptions("file,prefix=1")
|
||
require.NoError(t, err)
|
||
|
||
got := Path(ctx, test.path, true)
|
||
assert.Equal(t, test.want, got)
|
||
}
|
||
}
|
||
|
||
func TestDirTagOnDir(t *testing.T) {
|
||
for _, test := range []struct {
|
||
path string
|
||
want string
|
||
}{
|
||
{"a/b", "1a/1b"},
|
||
} {
|
||
ctx, err := newOptions("dir,prefix=1")
|
||
require.NoError(t, err)
|
||
|
||
got := Path(ctx, test.path, true)
|
||
assert.Equal(t, test.want, got)
|
||
}
|
||
}
|
||
|
||
func TestVarious(t *testing.T) {
|
||
for _, test := range []struct {
|
||
path string
|
||
want string
|
||
flags []string
|
||
}{
|
||
{"stories/The Quick Brown Fox!.txt", "STORIES/THE QUICK BROWN FOX!.TXT", []string{"all,uppercase"}},
|
||
{"stories/The Quick Brown Fox!.txt", "stories/The Slow Brown Turtle!.txt", []string{"all,replace=Fox:Turtle", "all,replace=Quick:Slow"}},
|
||
{"stories/The Quick Brown Fox!.txt", "c3Rvcmllcw==/VGhlIFF1aWNrIEJyb3duIEZveCEudHh0", []string{"all,base64encode"}},
|
||
{"c3Rvcmllcw==/VGhlIFF1aWNrIEJyb3duIEZveCEudHh0", "stories/The Quick Brown Fox!.txt", []string{"all,base64decode"}},
|
||
{"stories/The Quick Brown 🦊 Fox Went to the Café!.txt", "stories/The Quick Brown 🦊 Fox Went to the Café!.txt", []string{"all,nfc"}},
|
||
{"stories/The Quick Brown 🦊 Fox Went to the Café!.txt", "stories/The Quick Brown 🦊 Fox Went to the Café!.txt", []string{"all,nfd"}},
|
||
{"stories/The Quick Brown 🦊 Fox!.txt", "stories/The Quick Brown Fox!.txt", []string{"all,ascii"}},
|
||
{"stories/The Quick Brown 🦊 Fox!.txt", "stories/The+Quick+Brown+%F0%9F%A6%8A+Fox%21.txt", []string{"all,url"}},
|
||
{"stories/The Quick Brown Fox!.txt", "stories/The Quick Brown Fox!", []string{"all,trimsuffix=.txt"}},
|
||
{"stories/The Quick Brown Fox!.txt", "OLD_stories/OLD_The Quick Brown Fox!.txt", []string{"all,prefix=OLD_"}},
|
||
{"stories/The Quick Brown 🦊 Fox Went to the Café!.txt", "stories/The Quick Brown _ Fox Went to the Caf_!.txt", []string{"all,charmap=ISO-8859-7"}},
|
||
{"stories/The Quick Brown Fox: A Memoir [draft].txt", "stories/The Quick Brown Fox: A Memoir [draft].txt", []string{"all,encoder=Colon,SquareBracket"}},
|
||
{"stories/The Quick Brown 🦊 Fox Went to the Café!.txt", "stories/The Quick Brown 🦊 Fox", []string{"all,truncate=21"}},
|
||
{"stories/The Quick Brown Fox!.txt", "stories/The Quick Brown Fox!.txt", []string{"all,command=echo"}},
|
||
{"stories/The Quick Brown Fox!.txt", "stories/The Quick Brown Fox!.txt-" + time.Now().Local().Format("20060102"), []string{"date=-{YYYYMMDD}"}},
|
||
{"stories/The Quick Brown Fox!.txt", "stories/The Quick Brown Fox!.txt-" + time.Now().Local().Format("2006-01-02 0304PM"), []string{"date=-{macfriendlytime}"}},
|
||
{"stories/The Quick Brown Fox!.txt", "ababababababab/ababab ababababab ababababab ababab!abababab", []string{"all,regex=[\\.\\w]/ab"}},
|
||
} {
|
||
ctx, err := newOptions(test.flags...)
|
||
require.NoError(t, err)
|
||
|
||
got := Path(ctx, test.path, false)
|
||
assert.Equal(t, test.want, got)
|
||
}
|
||
}
|