chore: establish YCode replication baseline and TODO
This commit is contained in:
commit
6dc59f89ba
1118 files changed
+196002
No files matched your search
@@ -0,0 +1,35 @@
|
||||
import { promises as fs } from 'node:fs'
|
||||
import { dirname, isAbsolute, relative, resolve, sep, join } from 'node:path'
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import type { RevertChange } from '@shared/revert'
|
||||
|
||||
async function replaceFile(path: string, content: string | null): Promise<void> {
|
||||
if (content === null) { await fs.unlink(path); return }
|
||||
const temporary = join(dirname(path), `.ycode-restore-${randomUUID()}.tmp`)
|
||||
try { await fs.writeFile(temporary, content, 'utf8'); await fs.rename(temporary, path) }
|
||||
finally { await fs.unlink(temporary).catch(() => undefined) }
|
||||
}
|
||||
/** Validate every current file before applying any change; roll back if a write fails. */
|
||||
export async function restoreWorkspaceFiles(workspace: string, changes: RevertChange[]): Promise<() => Promise<void>> {
|
||||
const root = await fs.realpath(workspace)
|
||||
const validated: RevertChange[] = []
|
||||
for (const change of changes) {
|
||||
const path = await fs.realpath(resolve(change.path))
|
||||
const rel = relative(root, path)
|
||||
if (!rel || rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel)) throw new Error('恢复文件不在当前工作区内')
|
||||
if (await fs.readFile(path, 'utf8') !== change.after) throw new Error(`文件已被外部修改,未执行恢复:${rel}`)
|
||||
validated.push({ ...change, path })
|
||||
}
|
||||
const applied: RevertChange[] = []
|
||||
const undo = async (): Promise<void> => {
|
||||
for (const change of [...applied].reverse()) await replaceFile(change.path, change.after)
|
||||
}
|
||||
try {
|
||||
for (const change of validated) {
|
||||
if (await fs.readFile(change.path, 'utf8') !== change.after) throw new Error('文件在恢复前已变化')
|
||||
await replaceFile(change.path, change.before)
|
||||
applied.push(change)
|
||||
}
|
||||
} catch (error) { await undo(); throw error }
|
||||
return undo
|
||||
}
|
||||
Reference in new issue
Block a user