mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-26 20:12:38 +08:00
fix: Include notes directory in backup when configured outside Data folder
- Parse notes path from backup data during backup process
- If notes are outside {userData}/Data, backup them separately to Notes folder
- On restore, restore Notes folder to configured location
- Handles both default and custom notes paths correctly
This ensures users don't lose their notes when using custom paths.
Co-authored-by: DeJeune <67425183+DeJeune@users.noreply.github.com>
This commit is contained in:
parent
6493f1853d
commit
4269a32cfb
@ -11,6 +11,7 @@ import * as path from 'path'
|
||||
import type { CreateDirectoryOptions, FileStat } from 'webdav'
|
||||
|
||||
import { getDataPath } from '../utils'
|
||||
import { expandNotesPath } from '../utils/file'
|
||||
import S3Storage from './S3Storage'
|
||||
import WebDav from './WebDav'
|
||||
import { windowService } from './WindowService'
|
||||
@ -240,11 +241,49 @@ class BackupManager {
|
||||
// 使用流式复制
|
||||
await this.copyDirWithProgress(sourcePath, tempDataDir, (size) => {
|
||||
copiedSize += size
|
||||
const progress = Math.min(50, Math.floor((copiedSize / totalSize) * 50))
|
||||
const progress = Math.min(45, Math.floor((copiedSize / totalSize) * 45))
|
||||
onProgress({ stage: 'copying_files', progress, total: 100 })
|
||||
})
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
onProgress({ stage: 'preparing_compression', progress: 50, total: 100 })
|
||||
} else {
|
||||
logger.debug('Skip the backup of the file')
|
||||
@ -399,13 +438,52 @@ class BackupManager {
|
||||
// 使用流式复制
|
||||
await this.copyDirWithProgress(sourcePath, destPath, (size) => {
|
||||
copiedSize += size
|
||||
const progress = Math.min(85, 35 + Math.floor((copiedSize / totalSize) * 50))
|
||||
const progress = Math.min(75, 35 + Math.floor((copiedSize / totalSize) * 40))
|
||||
onProgress({ stage: 'copying_files', progress, total: 100 })
|
||||
})
|
||||
} else {
|
||||
logger.debug('skipBackupFile is true, skip restoring Data directory')
|
||||
}
|
||||
|
||||
// 检查并恢复外部 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)
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug('step 4: clean up temp directory')
|
||||
// 清理临时目录
|
||||
await this.setWritableRecursive(this.tempDir)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user