mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-24 03:04:21 +01:00
core: prevent file deletion when reverting changes to existing files
This commit is contained in:
@@ -105,8 +105,17 @@ export namespace Snapshot {
|
||||
.cwd(Instance.worktree)
|
||||
.nothrow()
|
||||
if (result.exitCode !== 0) {
|
||||
log.info("file not found in history, deleting", { file })
|
||||
await fs.unlink(file).catch(() => {})
|
||||
const relativePath = path.relative(Instance.worktree, file)
|
||||
const checkTree = await $`git --git-dir=${git} ls-tree ${item.hash} -- ${relativePath}`
|
||||
.quiet()
|
||||
.cwd(Instance.worktree)
|
||||
.nothrow()
|
||||
if (checkTree.exitCode === 0 && checkTree.text().trim()) {
|
||||
log.info("file existed in snapshot but checkout failed, keeping", { file })
|
||||
} else {
|
||||
log.info("file did not exist in snapshot, deleting", { file })
|
||||
await fs.unlink(file).catch(() => {})
|
||||
}
|
||||
}
|
||||
files.add(file)
|
||||
}
|
||||
|
||||
@@ -532,3 +532,55 @@ test("restore function", async () => {
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test("revert should not delete files that existed but were deleted in snapshot", async () => {
|
||||
await using tmp = await bootstrap()
|
||||
await Instance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
const snapshot1 = await Snapshot.track()
|
||||
expect(snapshot1).toBeTruthy()
|
||||
|
||||
await $`rm ${tmp.path}/a.txt`.quiet()
|
||||
|
||||
const snapshot2 = await Snapshot.track()
|
||||
expect(snapshot2).toBeTruthy()
|
||||
|
||||
await Bun.write(`${tmp.path}/a.txt`, "recreated content")
|
||||
|
||||
const patch = await Snapshot.patch(snapshot2!)
|
||||
expect(patch.files).toContain(`${tmp.path}/a.txt`)
|
||||
|
||||
await Snapshot.revert([patch])
|
||||
|
||||
expect(await Bun.file(`${tmp.path}/a.txt`).exists()).toBe(false)
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test("revert preserves file that existed in snapshot when deleted then recreated", async () => {
|
||||
await using tmp = await bootstrap()
|
||||
await Instance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
await Bun.write(`${tmp.path}/existing.txt`, "original content")
|
||||
|
||||
const snapshot = await Snapshot.track()
|
||||
expect(snapshot).toBeTruthy()
|
||||
|
||||
await $`rm ${tmp.path}/existing.txt`.quiet()
|
||||
await Bun.write(`${tmp.path}/existing.txt`, "recreated")
|
||||
await Bun.write(`${tmp.path}/newfile.txt`, "new")
|
||||
|
||||
const patch = await Snapshot.patch(snapshot!)
|
||||
expect(patch.files).toContain(`${tmp.path}/existing.txt`)
|
||||
expect(patch.files).toContain(`${tmp.path}/newfile.txt`)
|
||||
|
||||
await Snapshot.revert([patch])
|
||||
|
||||
expect(await Bun.file(`${tmp.path}/newfile.txt`).exists()).toBe(false)
|
||||
expect(await Bun.file(`${tmp.path}/existing.txt`).exists()).toBe(true)
|
||||
expect(await Bun.file(`${tmp.path}/existing.txt`).text()).toBe("original content")
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user