diff --git a/internal/fs/fs.go b/internal/fs/fs.go index a5ec3a2b99..69dd8565e0 100644 --- a/internal/fs/fs.go +++ b/internal/fs/fs.go @@ -2100,12 +2100,13 @@ func (fs *fileSystem) renameHierarchicalDir(ctx context.Context, oldParent inode if err = fs.checkDirNotEmpty(newDirInode, newName); err != nil { return err } - // It refers empty dest directory - // Since RenameFolder APIis not allowing to rename existing empty directory. We are deleting it first and then doing rename. + + // This refers to an empty destination directory. + // The RenameFolder API does not allow renaming to an existing empty directory. + // As a workaround, we delete the directory first and then perform rename. newParent.Lock() err = newParent.DeleteChildDir(ctx, newDirName.GcsObjectName(), false, newDirInode) newParent.Unlock() - pendingInodes = append(pendingInodes, newDirInode) } // Note:The renameDirLimit is not utilized in the folder rename operation because there is no user-defined limit on new renames. diff --git a/internal/fs/hns_bucket_test.go b/internal/fs/hns_bucket_test.go index aecd6bdf36..cc923dd987 100644 --- a/internal/fs/hns_bucket_test.go +++ b/internal/fs/hns_bucket_test.go @@ -15,7 +15,9 @@ package fs_test import ( + "fmt" "os" + "os/exec" "path" "strings" "testing" @@ -215,6 +217,32 @@ func (t *HNSBucketTests) TestRenameFolderWithSameParent() { assert.ElementsMatch(t.T(), actualDirEntries, expectedFooDirEntries) } +func (t *HNSBucketTests) TestRenameFolderWithExistingEmptyDestDirectory() { + oldDirPath := path.Join(mntDir, "foo", "test") + _, err = os.Stat(oldDirPath) + require.NoError(t.T(), err) + newDirPath := path.Join(mntDir, "foo", "test2") + _, err = os.Stat(newDirPath) + require.NoError(t.T(), err) + + // Go's Rename function does not support renaming a directory into an existing empty directory. + // To achieve this, we call a Python rename function as a workaround. + cmd := exec.Command("python", "-c", fmt.Sprintf("import os; os.rename('%s', '%s')", oldDirPath, newDirPath)) + _, err = cmd.CombinedOutput() + + assert.NoError(t.T(), err) + _, err = os.Stat(oldDirPath) + assert.Error(t.T(), err) + assert.True(t.T(), strings.Contains(err.Error(), "no such file or directory")) + _, err = os.Stat(newDirPath) + assert.NoError(t.T(), err) + dirEntries, err := os.ReadDir(newDirPath) + assert.NoError(t.T(), err) + assert.Equal(t.T(), 1, len(dirEntries)) + assert.Equal(t.T(), "file3.txt", dirEntries[0].Name()) + assert.False(t.T(), dirEntries[0].IsDir()) +} + func (t *HNSBucketTests) TestRenameFolderWithDifferentParents() { oldDirPath := path.Join(mntDir, "foo") _, err = os.Stat(oldDirPath)