ReviewOS

also looking at this

pantry-pm/pantry

fix: preserve sources when removing linked workspace directories

#247
Merged chris wants to merge codex/preserve-linked-workspace-sources into main
4 files +98 -46

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

.github/scripts/windows-native-tools.tsmodified+16-4
Changes to .github/scripts/windows-native-tools.ts
@@ -1,5 +1,5 @@
11import assert from 'node:assert/strict'
2import { mkdir, mkdtemp, lstat, rename, rm } from 'node:fs/promises'
2import { mkdir, mkdtemp, lstat, readFile, rm } from 'node:fs/promises'
33import { tmpdir } from 'node:os'
44import { join } from 'node:path'
55import { installPackage } from '../../packages/ts-pantry/src/installer'
@@ -9,8 +9,8 @@ const artifacts = join(import.meta.dir, '../../artifacts/windows-native-tools')
99await mkdir(artifacts, { recursive: true })
1010const root = await mkdtemp(join(tmpdir(), 'pantry native Windows '))
1111const proof: Record<string, unknown> = {}
12async function run(name: string, command: string[]): Promise<string> {
13 const child = Bun.spawn(command, { cwd: root, env: { ...process.env, NO_COLOR: '1' }, stdout: 'pipe', stderr: 'pipe' })
12async function run(name: string, command: string[], environment: Record<string, string> = {}): Promise<string> {
13 const child = Bun.spawn(command, { cwd: root, env: { ...process.env, NO_COLOR: '1', ...environment }, stdout: 'pipe', stderr: 'pipe' })
1414 const timeout = setTimeout(() => child.kill(), 180_000)
1515 try {
1616 const [code, stdout, stderr] = await Promise.all([child.exited, new Response(child.stdout).text(), new Response(child.stderr).text()])
@@ -28,18 +28,30 @@ try {
2828 proof.cliVersion = version
2929 let tree = join(root, 'pantry')
3030 await installPackage('ziglang.org', '0.17.0', { installDir: tree })
31 const compilerSha256 = Bun.SHA256.hash(await readFile(join(tree, '.bin/zig.exe')), 'hex')
32 proof.compilerSha256 = compilerSha256
3133 const source = join(root, 'fixture.zig')
3234 await Bun.write(source, 'const std = ; pub fn main() void { std.debug.print("NATIVE_ZIG_STDLIB_OK\\n", .{}); }\n')
3335 for (const phase of ['installed', 'relocated']) {
3436 const alias = join(tree, '.bin/zig.exe')
3537 assert((await lstat(alias)).isSymbolicLink())
38 assert.equal(Bun.SHA256.hash(await readFile(alias), 'hex'), compilerSha256)
3639 assert.equal((await run(`${phase}-version`, [alias, 'version'])).trim(), '0.17.0')
3740 const output = join(root, `${phase}.exe`)
3841 await run(`${phase}-compile`, [alias, 'build-exe', source, '-OReleaseSafe', `-femit-bin=${output}`])
3942 assert.equal((await run(`${phase}-execute`, [output])).trim(), 'NATIVE_ZIG_STDLIB_OK')
4043 if (phase === 'installed') {
4144 const moved = join(root, 'moved pantry')
42 await rename(tree, moved)
45 // Exercise the Windows user operation itself. Bun 1.4.3's rename rejects
46 // this installed tree with EPERM while the native Windows move succeeds.
47 // One native move must complete; source absence and the next phase's
48 // symlink, byte identity, compile and execution assertions stay required.
49 await run('relocate-prefix', ['powershell', '-NoProfile', '-NonInteractive', '-Command', 'Move-Item -LiteralPath $env:PANTRY_RELOCATION_SOURCE -Destination $env:PANTRY_RELOCATION_DESTINATION -ErrorAction Stop'], {
50 PANTRY_RELOCATION_SOURCE: tree,
51 PANTRY_RELOCATION_DESTINATION: moved,
52 })
53 await assert.rejects(lstat(tree), { code: 'ENOENT' })
54 proof.prefixRelocatedByNativeWindows = true
4355 tree = moved
4456 }
4557 }