From 0ce75add5aa115ca81662c7a4fb31fd1756c6491 Mon Sep 17 00:00:00 2001 From: jzunigax2 <125698953+jzunigax2@users.noreply.github.com> Date: Mon, 13 Apr 2026 11:17:16 +0200 Subject: [PATCH] internxt: add Move and DirMove methods for server-side file and directory operations --- backend/internxt/internxt.go | 74 ++++++++++++++++++++++++++++++++++++ go.mod | 2 +- go.sum | 6 +-- 3 files changed, 77 insertions(+), 5 deletions(-) diff --git a/backend/internxt/internxt.go b/backend/internxt/internxt.go index 58c9f1e21..af317999f 100644 --- a/backend/internxt/internxt.go +++ b/backend/internxt/internxt.go @@ -830,6 +830,80 @@ func (f *Fs) About(ctx context.Context) (*fs.Usage, error) { return usage, nil } +// Move moves a file to a new location +func (f *Fs) Move(ctx context.Context, src fs.Object, remote string) (fs.Object, error) { + srcObj, ok := src.(*Object) + if !ok { + return nil, fs.ErrorCantMove + } + + if srcObj.uuid == "" { + return nil, fs.ErrorCantMove + } + + leaf, directoryID, err := f.dirCache.FindPath(ctx, remote, true) + if err != nil { + return nil, err + } + + // Parse name and extension from the leaf + baseName := f.opt.Encoding.FromStandardName(leaf) + newName := strings.TrimSuffix(baseName, path.Ext(baseName)) + newType := strings.TrimPrefix(path.Ext(baseName), ".") + + // Move the file server-side + err = f.pacer.Call(func() (bool, error) { + err := files.MoveFile(ctx, f.cfg, srcObj.uuid, directoryID, newName, newType) + return f.shouldRetry(ctx, err) + }) + if err != nil { + return nil, err + } + + dstObj := &Object{ + f: f, + remote: remote, + id: srcObj.id, + uuid: srcObj.uuid, + size: srcObj.size, + modTime: srcObj.modTime, + } + + return dstObj, nil +} + +// DirMove moves src, srcRemote to this remote at dstRemote +// using server-side move operations. +// +// Will only be called if src.Fs().Name() == f.Name() +// +// If it isn't possible then return fs.ErrorCantDirMove +// +// If destination exists then return fs.ErrorDirExists +func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string) error { + srcFs, ok := src.(*Fs) + if !ok { + return fs.ErrorCantDirMove + } + + srcID, _, _, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote) + if err != nil { + return err + } + + encodedLeaf := f.opt.Encoding.FromStandardName(dstLeaf) + err = f.pacer.Call(func() (bool, error) { + err := folders.MoveFolder(ctx, f.cfg, srcID, dstDirectoryID, encodedLeaf) + return f.shouldRetry(ctx, err) + }) + if err != nil { + return err + } + + srcFs.dirCache.FlushDir(srcRemote) + return nil +} + // Shutdown the backend, closing any background tasks and any cached // connections. func (f *Fs) Shutdown(ctx context.Context) error { diff --git a/go.mod b/go.mod index 933d21ed1..d18e86fc4 100644 --- a/go.mod +++ b/go.mod @@ -46,7 +46,7 @@ require ( github.com/golang-jwt/jwt/v5 v5.3.1 github.com/google/uuid v1.6.0 github.com/hanwen/go-fuse/v2 v2.9.0 - github.com/internxt/rclone-adapter v0.0.0-20260331173834-036f908d0160 + github.com/internxt/rclone-adapter v0.0.0-20260708165336-dd6561bacfa2 github.com/jcmturner/gokrb5/v8 v8.4.4 github.com/jlaffaye/ftp v0.2.1-0.20251026020404-6602e981a1bb github.com/josephspurrier/goversioninfo v1.5.0 diff --git a/go.sum b/go.sum index 025b70e66..ebc56e36b 100644 --- a/go.sum +++ b/go.sum @@ -204,8 +204,6 @@ github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= github.com/cloudinary/cloudinary-go/v2 v2.15.0 h1:iLoIwb7BJECHTbNcmIhYDsQhoZiACWGNvEpyqQy97Dk= github.com/cloudinary/cloudinary-go/v2 v2.15.0/go.mod h1:ireC4gqVetsjVhYlwjUJwKTbZuWjEIynbR9zQTlqsvo= -github.com/cloudsoda/go-smb2 v0.0.0-20250228001242-d4c70e6251cc h1:t8YjNUCt1DimB4HCIXBztwWMhgxr5yG5/YaRl9Afdfg= -github.com/cloudsoda/go-smb2 v0.0.0-20250228001242-d4c70e6251cc/go.mod h1:CgWpFCFWzzEA5hVkhAc6DZZzGd3czx+BblvOzjmg6KA= github.com/cloudsoda/go-smb2 v0.0.0-20260701064823-d8c5600d73b8 h1:+KC2I+emnT6ccWmo7IHbtchGc/vFqAxUuovo2eUgMuM= github.com/cloudsoda/go-smb2 v0.0.0-20260701064823-d8c5600d73b8/go.mod h1:1pQXB0vAlzRlqcY7LYKOOZMw0wKfJPFxTLsJRF2Gswo= github.com/cloudsoda/sddl v0.0.0-20250224235906-926454e91efc h1:0xCWmFKBmarCqqqLeM7jFBSw/Or81UEElFqO8MY+GDs= @@ -428,8 +426,8 @@ github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyf github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/internxt/rclone-adapter v0.0.0-20260331173834-036f908d0160 h1:PV6ipOJN0JIek4dqPqsTtenQmjI1SZntCUgPzhfk9gM= -github.com/internxt/rclone-adapter v0.0.0-20260331173834-036f908d0160/go.mod h1:yRuPDnHgGmsbvopF0amMqXxr4n32GynzX5GTwFYDHaw= +github.com/internxt/rclone-adapter v0.0.0-20260708165336-dd6561bacfa2 h1:ZeebPK9Bnpy40uTuneEeVMYaMMerol3qsmIvzD0EIAk= +github.com/internxt/rclone-adapter v0.0.0-20260708165336-dd6561bacfa2/go.mod h1:4jGLEnNHyWOVSGn89IeWUVqlKCEitOM3D32/XypGy/o= github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=