fix(electron): prevent active data directory deletion

This commit is contained in:
digua committed 2026-07-19 00:24:50 +08:00
1 parent dd6765baf3
commit 23e145427c
3 files changed
+36 -7

No files matched your search

+18 -7
View File
@@ -6,7 +6,7 @@ import { app } from 'electron'
import * as fs from 'node:fs'
import * as path from 'node:path'
import { loadConfig, writeConfigField } from '@openchatlab/config'
import { copyDirMerge, copyDirRecursive, writeMigrationLog } from '../utils/pathUtils'
import { arePathsEqual, copyDirMerge, copyDirRecursive, writeMigrationLog } from '../utils/pathUtils'
import { shouldMarkUnifiedDirMigrationDone } from '../utils/unifiedDirMigration'
import {
ensureDir,
@@ -47,12 +47,8 @@ export function getLegacyDataDir(): string {
export function needsLegacyMigration(): boolean {
const legacyDir = getLegacyDataDir()
// 检查 Documents/ChatLab 是否存在
if (fs.existsSync(legacyDir)) {
return true
}
return false
// 用户可以主动将 Documents/ChatLab 设为当前数据目录,此时它不是待迁移的旧目录。
return fs.existsSync(legacyDir) && !arePathsEqual(legacyDir, getUserDataDir())
}
/**
@@ -138,6 +134,14 @@ export function migrateFromLegacyDir(): { success: boolean; migratedDirs: string
return { success: true, migratedDirs: [] }
}
// 迁移函数包含递归删除,必须在执行层再次阻止源目录与当前数据目录相同。
if (arePathsEqual(legacyDir, newDir)) {
const message = `Legacy migration skipped because source is the active data directory: ${legacyDir}`
console.warn(`[Paths] ${message}`)
writeMigrationLog(getLogsDir(), message, ensureDir)
return { success: true, migratedDirs: [] }
}
// 获取旧目录下的所有子目录和文件
const entries = fs.readdirSync(legacyDir, { withFileTypes: true })
const dirsToMigrate = entries
@@ -198,6 +202,13 @@ export function removeLegacyDir(): boolean {
return true
}
if (arePathsEqual(legacyDir, getUserDataDir())) {
const message = `Legacy directory removal blocked because it is the active data directory: ${legacyDir}`
console.error(`[Paths] ${message}`)
writeMigrationLog(getLogsDir(), message, ensureDir)
return false
}
try {
fs.rmSync(legacyDir, { recursive: true, force: true })
console.log(`[Paths] Removed legacy directory: ${legacyDir}`)
+11
View File
@@ -102,6 +102,17 @@ test('desktop paths preserve data across configured and legacy directory migrati
fs.writeFileSync(path.join(legacyDir, 'databases', 'legacy.db'), 'legacy', 'utf-8')
fs.writeFileSync(path.join(legacyDir, 'temp', 'stale.tmp'), 'temporary', 'utf-8')
configuredUserDataDir = legacyDir
paths.setCachedUserDataDir(legacyDir)
assert.equal(paths.needsLegacyMigration(), false)
const sameDirResult = paths.migrateFromLegacyDir()
assert.equal(sameDirResult.success, true)
assert.equal(fs.readFileSync(path.join(legacyDir, 'databases', 'legacy.db'), 'utf-8'), 'legacy')
assert.equal(paths.removeLegacyDir(), false)
assert.equal(fs.readFileSync(path.join(legacyDir, 'databases', 'legacy.db'), 'utf-8'), 'legacy')
configuredUserDataDir = targetDir
paths.setCachedUserDataDir(targetDir)
assert.equal(paths.needsLegacyMigration(), true)
const legacyResult = paths.migrateFromLegacyDir()
assert.equal(legacyResult.success, true)
+7
View File
@@ -28,6 +28,13 @@ function normalizePathForCompare(input: string): string {
return process.platform === 'win32' ? normalized.toLowerCase() : normalized
}
/**
* 判断两个路径是否指向同一个规范化位置
*/
export function arePathsEqual(first: string, second: string): boolean {
return normalizePathForCompare(first) === normalizePathForCompare(second)
}
/**
* 判断 child 是否为 parent 的子目录
*/