internxt: fix "directory not empty" and stale directories after moves and deletes

The Internxt API serves listings from read replicas which lag behind
writes, so for a short while after files or directories are moved or
deleted they can still be listed in their old location.

This caused removing a directory which had just been emptied to fail
with "directory not empty" (eg when moving a directory without server
side directory moves or purging a directory) and a directory which had
just been moved to be found in its old location.

Remember the directories this process has moved or deleted and ignore
directory and file entries which contradict that when listing, finding
directories and checking a directory is empty before removing it.
This commit is contained in:
Nick Craig-Wood committed 2026-09-23 16:00:26 +01:00
1 parent ee26daecd8
commit 7ff5da8517
1 file changed
+17 -4
+17 -4
View File
@@ -474,8 +474,10 @@ func (f *Fs) Rmdir(ctx context.Context, dir string) error {
if err != nil {
return err
}
if len(childFolders) > 0 {
return fs.ErrorDirectoryNotEmpty
for _, e := range childFolders {
if !recent.stale(e.UUID, id, e.PlainName) {
return fs.ErrorDirectoryNotEmpty
}
}
var childFiles []folders.File
@@ -487,8 +489,10 @@ func (f *Fs) Rmdir(ctx context.Context, dir string) error {
if err != nil {
return err
}
if len(childFiles) > 0 {
return fs.ErrorDirectoryNotEmpty
for _, e := range childFiles {
if !recent.stale(e.UUID, id, joinNameExt(e.PlainName, e.Type)) {
return fs.ErrorDirectoryNotEmpty
}
}
// Delete the directory
@@ -502,6 +506,7 @@ func (f *Fs) Rmdir(ctx context.Context, dir string) error {
if err != nil {
return err
}
recent.deleted(id)
f.dirCache.FlushDir(dir)
return nil
@@ -520,6 +525,9 @@ func (f *Fs) FindLeaf(ctx context.Context, pathID, leaf string) (string, bool, e
return "", false, err
}
for _, e := range entries {
if recent.stale(e.UUID, pathID, e.PlainName) {
continue
}
if f.opt.Encoding.ToStandardName(e.PlainName) == leaf {
return e.UUID, true, nil
}
@@ -753,6 +761,9 @@ func (f *Fs) List(ctx context.Context, dir string) (fs.DirEntries, error) {
return nil, err
}
for _, e := range foldersList {
if recent.stale(e.UUID, dirID, e.PlainName) {
continue
}
remote := path.Join(dir, f.opt.Encoding.ToStandardName(e.PlainName))
out = append(out, fs.NewDir(remote, e.ModificationTime))
}
@@ -845,6 +856,7 @@ func (f *Fs) Remove(ctx context.Context, remote string) error {
if err != nil {
return err
}
recent.deleted(dirID)
f.dirCache.FlushDir(remote)
return nil
}
@@ -1026,6 +1038,7 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
if err != nil {
return err
}
recent.moved(srcID, dstDirectoryID, encodedLeaf)
srcFs.dirCache.FlushDir(srcRemote)
return nil