mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-10-25 17:54:34 +08:00
fix(import): ignore AppleDouble database sidecars
This commit is contained in:
1 parent
8eae64df8e
commit
1e339875e1
4 files changed
+48
-41
No files matched your search
@@ -20,6 +20,7 @@ import {
|
||||
computeAndSetOverviewCache,
|
||||
createImportPerfLogger,
|
||||
deleteSessionCache,
|
||||
listDatabaseCandidateIds,
|
||||
} from '@openchatlab/node-runtime'
|
||||
import type {
|
||||
AutoImportBatchItemResult,
|
||||
@@ -131,13 +132,7 @@ export async function autoImport(
|
||||
return sharedAutoImportFile(
|
||||
filePath,
|
||||
{
|
||||
listSessionIds: () =>
|
||||
fs.existsSync(getDbDir())
|
||||
? fs
|
||||
.readdirSync(getDbDir())
|
||||
.filter((name) => name.endsWith('.db'))
|
||||
.map((name) => name.slice(0, -3))
|
||||
: [],
|
||||
listSessionIds: () => listDatabaseCandidateIds(getDbDir()),
|
||||
openReadonly: (sessionId) => new BetterSqliteAdapter(openRawDatabase(getDbPath(sessionId), { readonly: true })),
|
||||
onProgress: (progress) => sendProgress(requestId, progress),
|
||||
sessionExists: (sessionId) => fs.existsSync(getDbPath(sessionId)),
|
||||
@@ -183,13 +178,7 @@ export async function autoImportBatch(
|
||||
},
|
||||
})),
|
||||
{
|
||||
listSessionIds: () =>
|
||||
fs.existsSync(getDbDir())
|
||||
? fs
|
||||
.readdirSync(getDbDir())
|
||||
.filter((name) => name.endsWith('.db'))
|
||||
.map((name) => name.slice(0, -3))
|
||||
: [],
|
||||
listSessionIds: () => listDatabaseCandidateIds(getDbDir()),
|
||||
openReadonly: (sessionId) => new BetterSqliteAdapter(openRawDatabase(getDbPath(sessionId), { readonly: true })),
|
||||
sessionExists: (sessionId) => fs.existsSync(getDbPath(sessionId)),
|
||||
createSession: (sourcePath, sourceFormatOptions, sessionId, itemProgress) =>
|
||||
|
||||
@@ -7,7 +7,7 @@ import Database from 'better-sqlite3'
|
||||
import type { PathProvider } from '@openchatlab/core'
|
||||
import { CHAT_DB_SCHEMA, CURRENT_SCHEMA_VERSION, getSessionInfo } from '@openchatlab/core'
|
||||
import { DataDirCompatibilityError, readDataDirCompatibilityMeta } from './data-dir-compat'
|
||||
import { DatabaseManager } from './database-manager'
|
||||
import { DatabaseManager, listDatabaseCandidateIds } from './database-manager'
|
||||
|
||||
const nativeBinding = path.resolve('apps/cli/native/better_sqlite3.node')
|
||||
|
||||
@@ -1031,3 +1031,20 @@ test('listSessionIds ignores non-ChatLab sqlite databases without migrating them
|
||||
assert.deepEqual(manager.listSessionIds(), [])
|
||||
manager.closeAll()
|
||||
})
|
||||
|
||||
test('database candidate enumeration ignores AppleDouble sidecars but keeps damaged databases visible', () => {
|
||||
const root = makeTempDir()
|
||||
const dbDir = path.join(root, 'data', 'databases')
|
||||
fs.mkdirSync(dbDir, { recursive: true })
|
||||
fs.writeFileSync(path.join(dbDir, '._chat_existing.db'), Buffer.from([0x00, 0x05, 0x16, 0x07]))
|
||||
|
||||
const manager = new DatabaseManager(createPathProvider(root), { nativeBinding, allowMissingRuntimeForTests: true })
|
||||
assert.deepEqual(listDatabaseCandidateIds(dbDir), [])
|
||||
assert.deepEqual(manager.listSessionIds(), [])
|
||||
assert.deepEqual(manager.listSessionIdsReadonly(), [])
|
||||
|
||||
fs.writeFileSync(path.join(dbDir, 'damaged.db'), 'not a sqlite database')
|
||||
assert.deepEqual(listDatabaseCandidateIds(dbDir), ['damaged'])
|
||||
assert.throws(() => manager.listSessionIds(), /file is not a database/)
|
||||
assert.throws(() => manager.listSessionIdsReadonly(), /file is not a database/)
|
||||
})
|
||||
@@ -52,6 +52,19 @@ interface OpenRawSessionDatabaseOptions {
|
||||
initializeChatTables?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* List database candidates that require further inspection.
|
||||
* macOS AppleDouble `._*` files contain metadata rather than SQLite data.
|
||||
*/
|
||||
export function listDatabaseCandidateIds(databaseDir: string): string[] {
|
||||
if (!fs.existsSync(databaseDir)) return []
|
||||
|
||||
return fs
|
||||
.readdirSync(databaseDir)
|
||||
.filter((fileName) => fileName.endsWith('.db') && !fileName.startsWith('._'))
|
||||
.map((fileName) => fileName.slice(0, -3))
|
||||
}
|
||||
|
||||
export class DatabaseManager {
|
||||
private cache = new Map<string, DatabaseAdapter>()
|
||||
private nativeBinding?: string
|
||||
@@ -185,17 +198,11 @@ export class DatabaseManager {
|
||||
this.assertCompatible()
|
||||
|
||||
const dbDir = this.pathProvider.getDatabaseDir()
|
||||
if (!fs.existsSync(dbDir)) return []
|
||||
|
||||
return fs
|
||||
.readdirSync(dbDir)
|
||||
.filter((f) => f.endsWith('.db'))
|
||||
.map((f) => f.replace('.db', ''))
|
||||
.filter((id) => {
|
||||
const db = this.open(id)
|
||||
if (!db) return false
|
||||
return isChatSessionDb(db)
|
||||
})
|
||||
return listDatabaseCandidateIds(dbDir).filter((id) => {
|
||||
const db = this.open(id)
|
||||
if (!db) return false
|
||||
return isChatSessionDb(db)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,20 +212,14 @@ export class DatabaseManager {
|
||||
this.assertCompatible()
|
||||
|
||||
const dbDir = this.pathProvider.getDatabaseDir()
|
||||
if (!fs.existsSync(dbDir)) return []
|
||||
|
||||
return fs
|
||||
.readdirSync(dbDir)
|
||||
.filter((fileName) => fileName.endsWith('.db'))
|
||||
.map((fileName) => fileName.replace('.db', ''))
|
||||
.filter((sessionId) => {
|
||||
const db = this.openRawSessionDatabase(sessionId, { readonly: true })
|
||||
try {
|
||||
return isChatSessionDb(db)
|
||||
} finally {
|
||||
db.close()
|
||||
}
|
||||
})
|
||||
return listDatabaseCandidateIds(dbDir).filter((sessionId) => {
|
||||
const db = this.openRawSessionDatabase(sessionId, { readonly: true })
|
||||
try {
|
||||
return isChatSessionDb(db)
|
||||
} finally {
|
||||
db.close()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
getUserDataDir(): string {
|
||||
|
||||
@@ -120,7 +120,7 @@ export {
|
||||
getSystemLogsDir,
|
||||
hasPendingElectronDataWarning,
|
||||
} from './node-path-provider'
|
||||
export { DatabaseManager } from './database-manager'
|
||||
export { DatabaseManager, listDatabaseCandidateIds } from './database-manager'
|
||||
export { createJiebaNlpProvider } from './jieba-nlp-provider'
|
||||
export {
|
||||
applyPendingNodeDataDirMigration,
|
||||
|
||||
Reference in new issue
Block a user