From ac9c6c204c30ff99d75e5d0ce0aa618be4b25a3e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Oct 2025 17:43:19 +0000 Subject: [PATCH] Fix notes move operation to handle cross-filesystem moves properly - Changed moveFile and moveDir to use copy+delete fallback when rename fails - Added private copyDirectory helper method for recursive directory copying - This ensures files are actually moved, not just copied, across different filesystems Co-authored-by: DeJeune <67425183+DeJeune@users.noreply.github.com> --- src/main/services/FileStorage.ts | 49 ++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/src/main/services/FileStorage.ts b/src/main/services/FileStorage.ts index 2244b97cb0..8fdb390c47 100644 --- a/src/main/services/FileStorage.ts +++ b/src/main/services/FileStorage.ts @@ -320,9 +320,17 @@ class FileStorage { await fs.promises.mkdir(destDir, { recursive: true }) } - // 移动文件 - await fs.promises.rename(filePath, newPath) - logger.debug(`File moved successfully: ${filePath} to ${newPath}`) + try { + // 尝试使用 rename,这是最快的方式 + await fs.promises.rename(filePath, newPath) + logger.debug(`File moved successfully: ${filePath} to ${newPath}`) + } catch (renameError: any) { + // 如果 rename 失败(例如跨文件系统移动),使用复制+删除的方式 + logger.debug(`Rename failed, using copy+delete approach: ${renameError.message}`) + await fs.promises.copyFile(filePath, newPath) + await fs.promises.unlink(filePath) + logger.debug(`File moved successfully using copy+delete: ${filePath} to ${newPath}`) + } } catch (error) { logger.error('Move file failed:', error as Error) throw error @@ -341,15 +349,44 @@ class FileStorage { await fs.promises.mkdir(parentDir, { recursive: true }) } - // 移动目录 - await fs.promises.rename(dirPath, newDirPath) - logger.debug(`Directory moved successfully: ${dirPath} to ${newDirPath}`) + try { + // 尝试使用 rename,这是最快的方式 + await fs.promises.rename(dirPath, newDirPath) + logger.debug(`Directory moved successfully: ${dirPath} to ${newDirPath}`) + } catch (renameError: any) { + // 如果 rename 失败(例如跨文件系统移动),使用复制+删除的方式 + logger.debug(`Rename failed, using copy+delete approach: ${renameError.message}`) + await this.copyDirectory(dirPath, newDirPath) + await fs.promises.rm(dirPath, { recursive: true, force: true }) + logger.debug(`Directory moved successfully using copy+delete: ${dirPath} to ${newDirPath}`) + } } catch (error) { logger.error('Move directory failed:', error as Error) throw error } } + /** + * 递归复制目录 + * @private + */ + private async copyDirectory(source: string, destination: string): Promise { + await fs.promises.mkdir(destination, { recursive: true }) + + const entries = await fs.promises.readdir(source, { withFileTypes: true }) + + for (const entry of entries) { + const sourcePath = path.join(source, entry.name) + const destPath = path.join(destination, entry.name) + + if (entry.isDirectory()) { + await this.copyDirectory(sourcePath, destPath) + } else { + await fs.promises.copyFile(sourcePath, destPath) + } + } + } + public renameFile = async (_: Electron.IpcMainInvokeEvent, filePath: string, newName: string): Promise => { try { if (!fs.existsSync(filePath)) {