diff --git a/src/main/services/BackupManager.ts b/src/main/services/BackupManager.ts index 6459eb0760..e414a73ee5 100644 --- a/src/main/services/BackupManager.ts +++ b/src/main/services/BackupManager.ts @@ -248,41 +248,7 @@ class BackupManager { await this.setWritableRecursive(tempDataDir) // 检查并备份 notes 目录(如果配置在 Data 目录外) - try { - const backupData = JSON.parse(data) - const persistData = JSON.parse(backupData.localStorage?.['persist:cherry-studio'] || '{}') - const noteState = JSON.parse(persistData.note || '{}') - const notesPath = noteState.notesPath - - if (notesPath) { - // 展开路径获取绝对路径 - const expandedNotesPath = expandNotesPath(notesPath) - const dataPath = path.join(app.getPath('userData'), 'Data') - const normalizedDataPath = path.normalize(dataPath) - const normalizedNotesPath = path.normalize(expandedNotesPath) - - // 检查 notes 是否在 Data 目录外 - const isOutsideData = - !normalizedNotesPath.startsWith(normalizedDataPath + path.sep) && - normalizedNotesPath !== normalizedDataPath - - if (isOutsideData && fs.existsSync(expandedNotesPath)) { - logger.info(`Backing up notes from external location: ${expandedNotesPath}`) - const tempNotesDir = path.join(this.tempDir, 'Notes') - await this.copyDirWithProgress(expandedNotesPath, tempNotesDir, (size) => { - // Notes backup progress from 45% to 50% - copiedSize += size - const notesProgress = 45 + Math.min(5, Math.floor((size / totalSize) * 5)) - onProgress({ stage: 'copying_notes', progress: notesProgress, total: 100 }) - }) - await this.setWritableRecursive(tempNotesDir) - logger.info('External notes directory backed up successfully') - } - } - } catch (error) { - // 如果解析失败或获取 notes 路径失败,继续备份其他内容 - logger.warn('Failed to parse notes path from backup data, skipping external notes backup', error as Error) - } + await this.backupExternalNotes(data, onProgress, totalSize, copiedSize) onProgress({ stage: 'preparing_compression', progress: 50, total: 100 }) } else { @@ -447,42 +413,7 @@ class BackupManager { // 检查并恢复外部 Notes 目录 logger.debug('step 3.5: check and restore external Notes directory') - const notesBackupPath = path.join(this.tempDir, 'Notes') - const notesExists = await fs.pathExists(notesBackupPath) - - if (notesExists) { - try { - // 从 data.json 中获取 notes 路径配置 - const backupData = JSON.parse(data) - const persistData = JSON.parse(backupData.localStorage?.['persist:cherry-studio'] || '{}') - const noteState = JSON.parse(persistData.note || '{}') - const notesPath = noteState.notesPath - - if (notesPath) { - const expandedNotesPath = expandNotesPath(notesPath) - logger.info(`Restoring notes to configured location: ${expandedNotesPath}`) - - // 确保目标目录的父目录存在 - await fs.ensureDir(path.dirname(expandedNotesPath)) - - // 如果目标已存在,先删除 - if (await fs.pathExists(expandedNotesPath)) { - await this.setWritableRecursive(expandedNotesPath) - await fs.remove(expandedNotesPath) - } - - // 复制 Notes 目录 - await this.copyDirWithProgress(notesBackupPath, expandedNotesPath, (size) => { - const progress = Math.min(85, 75 + Math.floor(size / 1000000)) - onProgress({ stage: 'copying_notes', progress, total: 100 }) - }) - - logger.info('External notes directory restored successfully') - } - } catch (error) { - logger.warn('Failed to restore external notes directory', error as Error) - } - } + await this.restoreExternalNotes(data, onProgress) logger.debug('step 4: clean up temp directory') // 清理临时目录 @@ -592,6 +523,103 @@ class BackupManager { return size } + /** + * Backup external notes directory if configured outside Data folder + * @param data - The backup data JSON string + * @param onProgress - Progress callback function + * @param totalSize - Total size of Data directory for progress calculation + * @param copiedSize - Current copied size for progress offset + */ + private async backupExternalNotes( + data: string, + onProgress: (processData: { stage: string; progress: number; total: number }) => void, + totalSize: number, + copiedSize: number + ): Promise { + try { + const backupData = JSON.parse(data) + const persistData = JSON.parse(backupData.localStorage?.['persist:cherry-studio'] || '{}') + const noteState = JSON.parse(persistData.note || '{}') + const notesPath = noteState.notesPath + + if (notesPath) { + // 展开路径获取绝对路径 + const expandedNotesPath = expandNotesPath(notesPath) + const dataPath = path.join(app.getPath('userData'), 'Data') + const normalizedDataPath = path.normalize(dataPath) + const normalizedNotesPath = path.normalize(expandedNotesPath) + + // 检查 notes 是否在 Data 目录外 + const isOutsideData = + !normalizedNotesPath.startsWith(normalizedDataPath + path.sep) && + normalizedNotesPath !== normalizedDataPath + + if (isOutsideData && fs.existsSync(expandedNotesPath)) { + logger.info(`Backing up notes from external location: ${expandedNotesPath}`) + const tempNotesDir = path.join(this.tempDir, 'Notes') + await this.copyDirWithProgress(expandedNotesPath, tempNotesDir, (size) => { + // Notes backup progress from 45% to 50% + copiedSize += size + const notesProgress = 45 + Math.min(5, Math.floor((size / totalSize) * 5)) + onProgress({ stage: 'copying_notes', progress: notesProgress, total: 100 }) + }) + await this.setWritableRecursive(tempNotesDir) + logger.info('External notes directory backed up successfully') + } + } + } catch (error) { + // 如果解析失败或获取 notes 路径失败,继续备份其他内容 + logger.warn('Failed to parse notes path from backup data, skipping external notes backup', error as Error) + } + } + + /** + * Restore external notes directory from backup + * @param data - The backup data JSON string + * @param onProgress - Progress callback function + */ + private async restoreExternalNotes( + data: string, + onProgress: (processData: { stage: string; progress: number; total: number }) => void + ): Promise { + const notesBackupPath = path.join(this.tempDir, 'Notes') + const notesExists = await fs.pathExists(notesBackupPath) + + if (notesExists) { + try { + // 从 data.json 中获取 notes 路径配置 + const backupData = JSON.parse(data) + const persistData = JSON.parse(backupData.localStorage?.['persist:cherry-studio'] || '{}') + const noteState = JSON.parse(persistData.note || '{}') + const notesPath = noteState.notesPath + + if (notesPath) { + const expandedNotesPath = expandNotesPath(notesPath) + logger.info(`Restoring notes to configured location: ${expandedNotesPath}`) + + // 确保目标目录的父目录存在 + await fs.ensureDir(path.dirname(expandedNotesPath)) + + // 如果目标已存在,先删除 + if (await fs.pathExists(expandedNotesPath)) { + await this.setWritableRecursive(expandedNotesPath) + await fs.remove(expandedNotesPath) + } + + // 复制 Notes 目录 + await this.copyDirWithProgress(notesBackupPath, expandedNotesPath, (size) => { + const progress = Math.min(85, 75 + Math.floor(size / 1000000)) + onProgress({ stage: 'copying_notes', progress, total: 100 }) + }) + + logger.info('External notes directory restored successfully') + } + } catch (error) { + logger.warn('Failed to restore external notes directory', error as Error) + } + } + } + private async copyDirWithProgress( source: string, destination: string,