memory: fix incorrect list entries when rooted at subdirectory

Before this change, List would return incorrect directory paths (relative to the
wrong root) if the Fs root pointed to a subdirectory. For example, listing dir
"a/b/c/d" of remote :memory: would work correctly, but listing dir "c/d" of
remote :memory:a/b would not, and would result in "Entry doesn't belong in
directory %q (contains subdir)" errors.

This change fixes the issue and adds a test to detect any other backends that
might have the same issue.
This commit is contained in:
nielash 2024-03-24 06:01:23 -04:00
parent 2b0a25a64d
commit f62e7b5b30
2 changed files with 24 additions and 1 deletions

View File

@ -296,7 +296,7 @@ func (f *Fs) list(ctx context.Context, bucket, directory, prefix string, addBuck
slash := strings.IndexRune(localPath, '/')
if slash >= 0 {
// send a directory if have a slash
dir := directory + localPath[:slash]
dir := strings.TrimPrefix(directory, f.rootDirectory+"/") + localPath[:slash]
if addBucket {
dir = path.Join(bucket, dir)
}

View File

@ -24,6 +24,7 @@ import (
"time"
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/cache"
"github.com/rclone/rclone/fs/config"
"github.com/rclone/rclone/fs/fserrors"
"github.com/rclone/rclone/fs/fspath"
@ -1209,6 +1210,28 @@ func Run(t *testing.T, opt *Opt) {
}, fs.GetModifyWindow(ctx, f))
})
// TestFsListRootedSubdir tests putting and listing with an Fs that is rooted at a subdirectory 2 levels down
TestFsListRootedSubdir := func(t *testing.T) {
skipIfNotOk(t)
newF, err := cache.Get(ctx, subRemoteName+"/hello? sausage/êé")
assert.NoError(t, err)
nestedFile := fstest.Item{
ModTime: fstest.Time("2001-02-03T04:05:06.499999999Z"),
Path: "a/b/c/d/e.txt",
}
_, _ = testPut(ctx, t, newF, &nestedFile)
objs, dirs, err := walk.GetAll(ctx, newF, "", true, 10)
require.NoError(t, err)
assert.Equal(t, []string{`Hello, 世界/ " ' @ < > & ? + ≠/z.txt`, nestedFile.Path}, objsToNames(objs))
assert.Equal(t, []string{`Hello, 世界`, `Hello, 世界/ " ' @ < > & ? + ≠`, "a", "a/b", "a/b/c", "a/b/c/d"}, dirsToNames(dirs))
// cleanup
err = operations.Purge(ctx, newF, "a")
require.NoError(t, err)
}
t.Run("FsListRootedSubdir", TestFsListRootedSubdir)
// TestFsCopy tests Copy
t.Run("FsCopy", func(t *testing.T) {
skipIfNotOk(t)