diff --git a/cmd/mountlib/context.go b/cmd/mountlib/context.go deleted file mode 100644 index f2ca4c77a..000000000 --- a/cmd/mountlib/context.go +++ /dev/null @@ -1,105 +0,0 @@ -package mountlib - -import ( - "reflect" - "sync" - - "github.com/rclone/rclone/fs/config/configstruct" - "github.com/rclone/rclone/fs/rc" - "github.com/rclone/rclone/vfs/vfscommon" -) - -var ( - vfsOptionsOnce sync.Once - vfsOptionsMap map[string]bool - mountOptionsOnce sync.Once - mountOptionsMap map[string]bool -) - -func initVfsOptions() { - vfsOptionsOnce.Do(func() { - vfsOptionsMap = make(map[string]bool, len(vfscommon.OptionsInfo)) - for _, opt := range vfscommon.OptionsInfo { - vfsOptionsMap[opt.Name] = true - } - }) -} - -func initMountOptions() { - mountOptionsOnce.Do(func() { - mountOptionsMap = make(map[string]bool, len(OptionsInfo)) - for _, opt := range OptionsInfo { - mountOptionsMap[opt.Name] = true - } - }) -} - -// isMap returns true if v's underlying type is a map -func isMap(v any) bool { - if v == nil { - return false - } - t := reflect.TypeOf(v) - for t.Kind() == reflect.Pointer { - t = t.Elem() - } - return t.Kind() == reflect.Map -} - -// parseVfsOptions parses VFS options from in (both flat and nested) and updates vfsOpt -func parseVfsOptions(in rc.Params, vfsOpt *vfscommon.Options) error { - initVfsOptions() - flatVfs := make(map[string]any) - for k, v := range in { - if vfsOptionsMap[k] { - if isMap(v) { - continue - } - flatVfs[k] = v - } - } - if len(flatVfs) > 0 { - err := configstruct.SetAny(flatVfs, vfsOpt) - if err != nil { - return err - } - for k := range flatVfs { - delete(in, k) - } - } - err := in.GetStructMissingOK("vfsOpt", vfsOpt) - if err != nil { - return err - } - delete(in, "vfsOpt") - return nil -} - -// parseMountOptions parses Mount options from in (both flat and nested) and updates mountOpt -func parseMountOptions(in rc.Params, mountOpt *Options) error { - initMountOptions() - flatMount := make(map[string]any) - for k, v := range in { - if mountOptionsMap[k] { - if isMap(v) { - continue - } - flatMount[k] = v - } - } - if len(flatMount) > 0 { - err := configstruct.SetAny(flatMount, mountOpt) - if err != nil { - return err - } - for k := range flatMount { - delete(in, k) - } - } - err := in.GetStructMissingOK("mountOpt", mountOpt) - if err != nil { - return err - } - delete(in, "mountOpt") - return nil -} diff --git a/cmd/mountlib/rc.go b/cmd/mountlib/rc.go index 362c33760..aab0daabe 100644 --- a/cmd/mountlib/rc.go +++ b/cmd/mountlib/rc.go @@ -105,13 +105,13 @@ func mountRc(ctx context.Context, in rc.Params) (out rc.Params, err error) { } vfsOpt := vfscommon.Opt - err = parseVfsOptions(in, &vfsOpt) + err = rc.ParseOptions(in, "vfsOpt", &vfsOpt) if err != nil { return nil, err } mountOpt := Opt - err = parseMountOptions(in, &mountOpt) + err = rc.ParseOptions(in, "mountOpt", &mountOpt) if err != nil { return nil, err } @@ -139,6 +139,15 @@ func mountRc(ctx context.Context, in rc.Params) (out rc.Params, err error) { return nil, err } + // Clean up consumed keys and check for leftovers + delete(in, "mountPoint") + delete(in, "mountType") + delete(in, "fs") + err = rc.CheckParamsUsed(in) + if err != nil { + return nil, err + } + mnt := NewMountPoint(mountFn, mountPoint, fdst, &mountOpt, &vfsOpt) _, err = mnt.Mount() if err != nil { diff --git a/cmd/mountlib/rc_test.go b/cmd/mountlib/rc_test.go index 4d316998b..d646cbc94 100644 --- a/cmd/mountlib/rc_test.go +++ b/cmd/mountlib/rc_test.go @@ -121,92 +121,11 @@ func TestRc(t *testing.T) { time.Sleep(100 * time.Millisecond) t.Run("Unmount", func(t *testing.T) { - _, err := unmount.Fn(ctx, in) + _, err := unmount.Fn(ctx, rc.Params{ + "mountPoint": mountPoint, + }) require.NoError(t, err) assert.Equal(t, 0, len(checkMountList())) }) }) } - -func TestRcFlatOptions(t *testing.T) { - // Disable tests under macOS and the CI since they are locking up - if runtime.GOOS == "darwin" { - testy.SkipUnreliable(t) - } - ctx := context.Background() - configfile.Install() - mount := rc.Calls.Get("mount/mount") - assert.NotNil(t, mount) - unmount := rc.Calls.Get("mount/unmount") - assert.NotNil(t, unmount) - getMountTypes := rc.Calls.Get("mount/types") - assert.NotNil(t, getMountTypes) - - localDir := t.TempDir() - err := os.WriteFile(filepath.Join(localDir, "file.txt"), []byte("hello"), 0666) - require.NoError(t, err) - - out, err := getMountTypes.Fn(ctx, nil) - require.NoError(t, err) - var mountTypes []string - err = out.GetStruct("mountTypes", &mountTypes) - require.NoError(t, err) - if len(mountTypes) == 0 { - t.Skip("Can't mount") - } - - mountPointFlat := t.TempDir() - if runtime.GOOS == "windows" { - require.NoError(t, os.RemoveAll(mountPointFlat)) - } - - in := rc.Params{ - "fs": localDir, - "mountPoint": mountPointFlat, - "file_perms": 0400, // flat VFS option - "volname": "MyTestVolume", // flat Mount option - } - - // mount - out, err = mount.Fn(ctx, in) - if err != nil { - t.Skipf("Mount failed - skipping test: %v", err) - } - - // check the returned mount point matches what we asked for - returnedMountPoint, err := out.GetString("mountPoint") - require.NoError(t, err) - assert.Equal(t, mountPointFlat, returnedMountPoint) - - // check that the flat options were consumed and removed from parameter map - _, ok := in["file_perms"] - assert.False(t, ok, "file_perms flat option should have been deleted") - _, ok = in["volname"] - assert.False(t, ok, "volname flat option should have been deleted") - - // unmount - _, err = unmount.Fn(ctx, rc.Params{ - "mountPoint": mountPointFlat, - }) - require.NoError(t, err) - - // FIXME wait a moment for the OS to release the mount point - time.Sleep(100 * time.Millisecond) -} - -func TestRcFlatOptionsNull(t *testing.T) { - ctx := context.Background() - configfile.Install() - mount := rc.Calls.Get("mount/mount") - assert.NotNil(t, mount) - - in := rc.Params{ - "fs": "some_fs", - "mountPoint": "some_mount_point", - "vfs_cache_mode": nil, // flat VFS option set to null - } - - _, err := mount.Fn(ctx, in) - assert.Error(t, err) - assert.Contains(t, err.Error(), "interpreting as string failed") -}