fix(fs): harden guarded-create publication

This commit is contained in:
Tianyi Cui
2026-08-09 17:40:41 +08:00
parent ceba53edd7
commit 7132b9730e
15 changed files with 207 additions and 40 deletions

View File

@@ -52,7 +52,10 @@ class FakeRemote {
nextRemoveError: unknown
canonicalOutput: string | undefined
abortAfterRename: AbortController | undefined
competitorBeforeLink: { path: string; data: string } | undefined
competitorBeforeLink:
| { path: string; kind: 'file'; data: string }
| { path: string; kind: 'directory' }
| undefined
guardedLinkOutput: string | undefined
disappearOnInfo = new Set<string>()
private clock = 1
@@ -257,7 +260,7 @@ class FakeRemote {
const chmod = /^chmod ([0-7]+) -- '([^']+)'$/.exec(command)
if (chmod !== null) this.required(chmod[2]!).mode = Number.parseInt(chmod[1]!, 8)
const guardedLink = new RegExp(
"^if ln -- '([^']+)' '([^']+)'; then printf created; "
"^if ln -T -- '([^']+)' '([^']+)'; then printf created; "
+ "elif test -e '[^']+' \\|\\| test -L '[^']+'; then printf exists; else exit 1; fi$",
).exec(command)
if (guardedLink !== null) {
@@ -269,7 +272,8 @@ class FakeRemote {
return { exitCode: 0, stdout, stderr: '' }
}
if (this.competitorBeforeLink?.path === to) {
this.file(to, this.competitorBeforeLink.data)
if (this.competitorBeforeLink.kind === 'directory') this.dir(to)
else this.file(to, this.competitorBeforeLink.data)
this.competitorBeforeLink = undefined
}
if (this.nodes.has(to)) return { exitCode: 0, stdout: 'exists', stderr: '' }
@@ -555,7 +559,7 @@ describe('E2BFileSystem atomic writes and edits', () => {
it('preserves a competitor created after the guarded-create probe', async () => {
const remote = new FakeRemote()
remote.competitorBeforeLink = { path: '/workspace/race.txt', data: 'competitor' }
remote.competitorBeforeLink = { path: '/workspace/race.txt', kind: 'file', data: 'competitor' }
const { fs } = await setup(remote)
await expectCode(
@@ -567,6 +571,21 @@ describe('E2BFileSystem atomic writes and edits', () => {
expect(remote.removals).toHaveLength(1)
})
it('preserves a competing directory during guarded-create publication', async () => {
const remote = new FakeRemote()
remote.competitorBeforeLink = { path: '/workspace/race-dir', kind: 'directory' }
const { fs } = await setup(remote)
await expectCode(
fs.writeText(await fs.resolve('race-dir'), 'ours', { kind: 'createIfAbsent' }),
'FS_NOT_OBSERVED',
)
expect(remote.nodes.get('/workspace/race-dir')?.type).toBe(FileType.DIR)
expect(remote.nodes.has('/workspace/race-dir/content')).toBe(false)
expect(remote.links).toHaveLength(0)
expect(remote.removals).toHaveLength(1)
})
it('rejects an invalid guarded-create publication response before claiming success', async () => {
const remote = new FakeRemote()
remote.guardedLinkOutput = 'unexpected'