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>
This commit is contained in:
copilot-swe-agent[bot] 2025-10-23 17:43:19 +00:00
parent f1bad06ae5
commit ac9c6c204c

View File

@ -320,9 +320,17 @@ class FileStorage {
await fs.promises.mkdir(destDir, { recursive: true })
}
// 移动文件
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 })
}
// 移动目录
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<void> {
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<void> => {
try {
if (!fs.existsSync(filePath)) {