From b9406099319a7a4e3fd8536cb85979ab1f0ef0b7 Mon Sep 17 00:00:00 2001 From: lullius <> Date: Sat, 2 Aug 2025 19:49:25 +0200 Subject: [PATCH 1/4] backend/internxt: Implemented Purge, now using purgeCheck for Rmdir and Purge --- backend/internxt/internxt.go | 52 +++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/backend/internxt/internxt.go b/backend/internxt/internxt.go index e3ea92ba74d56..8e5c91c4f32d3 100644 --- a/backend/internxt/internxt.go +++ b/backend/internxt/internxt.go @@ -4,6 +4,7 @@ package internxt import ( "bytes" "context" + "errors" "fmt" "io" "path" @@ -51,7 +52,7 @@ func init() { Default: false, Help: "Simulates empty files by uploading a small placeholder file instead. Alters the filename when uploading to keep track of empty files, but this is not visible through rclone.", }, - { + { Name: "use_2fa", Help: "Do you use 2FA to login?", Default: false, @@ -86,7 +87,7 @@ type Options struct { Password string `flag:"password" help:"Internxt account password"` Encoding encoder.MultiEncoder `config:"encoding"` SimulateEmptyFiles bool `config:"simulateEmptyFiles"` - Use2FA bool `config:"use_2fa" help:"Do you use 2FA to login?"` + Use2FA bool `config:"use_2fa" help:"Do you use 2FA to login?"` } // Fs represents an Internxt remote @@ -241,24 +242,48 @@ func (f *Fs) Mkdir(ctx context.Context, dir string) error { } // Rmdir removes a directory +// Returns an error if it isn't empty func (f *Fs) Rmdir(ctx context.Context, dir string) error { + return f.purgeCheck(ctx, dir, true) +} + +// Purge deletes the directory and all its contents +func (f *Fs) Purge(ctx context.Context, dir string) error { + return f.purgeCheck(ctx, dir, false) +} + +func (f *Fs) purgeCheck(ctx context.Context, dir string, check bool) (err error) { + root := path.Join(f.root, dir) + if root == "" { + return errors.New("can't purge root directory") + } + + // check that the directory exists id, err := f.dirCache.FindDir(ctx, dir, false) if err != nil { return fs.ErrorDirNotFound } - // Replace these calls with GetFolderContent? (fmt.Sprintf("/storage/v2/folder/%d%s", folderID, query)) - childFolders, err := folders.ListAllFolders(f.cfg, id) - if err != nil { - return err - } - childFiles, err := folders.ListAllFiles(f.cfg, id) - if err != nil { - return err - } + if check { + // Replace these calls with GetFolderContent? (fmt.Sprintf("/storage/v2/folder/%d%s", folderID, query)) + // Check folders and files separately in case we only need to call the API once. + childFolders, err := folders.ListAllFolders(f.cfg, id) + if err != nil { + return err + } + + if len(childFolders) > 0 { + return fs.ErrorDirectoryNotEmpty + } - if len(childFiles) > 0 || len(childFolders) > 0 { - return fs.ErrorDirectoryNotEmpty + childFiles, err := folders.ListAllFiles(f.cfg, id) + if err != nil { + return err + } + + if len(childFiles) > 0 { + return fs.ErrorDirectoryNotEmpty + } } err = folders.DeleteFolder(f.cfg, id) @@ -272,6 +297,7 @@ func (f *Fs) Rmdir(ctx context.Context, dir string) error { f.dirCache.FlushDir(dir) time.Sleep(500 * time.Millisecond) // REMOVE THIS, use pacer to check for consistency? return nil + } // FindLeaf looks for a sub‑folder named `leaf` under the Internxt folder `pathID`. From e3dc0cc3de13f6e4254e47c05d14b15e327aa336 Mon Sep 17 00:00:00 2001 From: lullius <> Date: Thu, 7 Aug 2025 08:29:28 +0200 Subject: [PATCH 2/4] backend/internxt: Remove EMPTY_FILE_EXT when updating an empty file with actual data --- backend/internxt/internxt.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/internxt/internxt.go b/backend/internxt/internxt.go index 8e5c91c4f32d3..f87782fe2f588 100644 --- a/backend/internxt/internxt.go +++ b/backend/internxt/internxt.go @@ -649,6 +649,11 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op } o.remote = o.remote + EMPTY_FILE_EXT } + } else { + if o.f.opt.SimulateEmptyFiles { + // Remove the suffix if we're updating an empty file with actual data + o.remote = strings.TrimSuffix(o.remote, EMPTY_FILE_EXT) + } } // Check if object exists on the server From 7ae44e405a121eef7d7e6d32d497462e343aef0c Mon Sep 17 00:00:00 2001 From: lullius <> Date: Sun, 10 Aug 2025 18:35:24 +0200 Subject: [PATCH 3/4] backend/internxt: Implemented About --- backend/internxt/internxt.go | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/backend/internxt/internxt.go b/backend/internxt/internxt.go index f87782fe2f588..d7158d7d0bcee 100644 --- a/backend/internxt/internxt.go +++ b/backend/internxt/internxt.go @@ -15,11 +15,11 @@ import ( "github.com/StarHack/go-internxt-drive/auth" "github.com/StarHack/go-internxt-drive/buckets" config "github.com/StarHack/go-internxt-drive/config" - rclone_config "github.com/rclone/rclone/fs/config" - "github.com/StarHack/go-internxt-drive/files" "github.com/StarHack/go-internxt-drive/folders" + "github.com/StarHack/go-internxt-drive/users" "github.com/rclone/rclone/fs" + rclone_config "github.com/rclone/rclone/fs/config" "github.com/rclone/rclone/fs/config/configmap" "github.com/rclone/rclone/fs/config/configstruct" "github.com/rclone/rclone/fs/config/obscure" @@ -613,6 +613,28 @@ func (o *Object) SetModTime(ctx context.Context, t time.Time) error { return fs.ErrorCantSetModTime } +// About gets quota information +func (f *Fs) About(ctx context.Context) (*fs.Usage, error) { + internxtLimit, err := users.GetLimit(f.cfg) + if err != nil { + return nil, err + } + + internxtUsage, err := users.GetUsage(f.cfg) + if err != nil { + return nil, err + } + + usage := &fs.Usage{ + Used: fs.NewUsageValue(internxtUsage.Drive), + } + + usage.Total = fs.NewUsageValue(internxtLimit.MaxSpaceBytes) + usage.Free = fs.NewUsageValue(*usage.Total - *usage.Used) + + return usage, nil +} + // Open opens a file for streaming func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (io.ReadCloser, error) { fs.FixRangeOption(options, o.size) From 3743ead2952f3a6eae92006e35c6204bbb84854a Mon Sep 17 00:00:00 2001 From: lullius <> Date: Sun, 10 Aug 2025 19:18:32 +0200 Subject: [PATCH 4/4] backend/internxt: Handle leading and trailing slashes --- backend/internxt/internxt.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/internxt/internxt.go b/backend/internxt/internxt.go index d7158d7d0bcee..16038b6dde0d7 100644 --- a/backend/internxt/internxt.go +++ b/backend/internxt/internxt.go @@ -192,6 +192,8 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e DirModTimeUpdatesOnWrite: false, }).Fill(ctx, f) + // Handle leading and trailing slashes + root = strings.Trim(root, "/") f.dirCache = dircache.New(root, cfg.RootFolderID, f) err = f.dirCache.FindRoot(ctx, false)