From 58483426cdd6f58ecd7a01e7a8304e2e8c2d28fa Mon Sep 17 00:00:00 2001 From: Dylan Conway <35280289+dylan-conway@users.noreply.github.com> Date: Wed, 10 Jul 2024 21:09:14 -0700 Subject: [PATCH] fix(install): call `GetFinalPathNameByHandle` on cwd for postinstall scripts (#12497) --- src/bun.js/api/bun/process.zig | 6 ++++-- src/install/lifecycle_script_runner.zig | 2 +- src/install/lockfile.zig | 21 ++++++++++++++++++--- test/cli/install/bun-workspaces.test.ts | 25 +++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/bun.js/api/bun/process.zig b/src/bun.js/api/bun/process.zig index 720269f3f3..850fc24b13 100644 --- a/src/bun.js/api/bun/process.zig +++ b/src/bun.js/api/bun/process.zig @@ -1513,8 +1513,10 @@ pub fn spawnProcessWindows( const allocator = stack_allocator.get(); const loop = options.windows.loop.platformEventLoop().uv_loop; - const cwd = try allocator.dupeZ(u8, options.cwd); - defer allocator.free(cwd); + var cwd_buf: bun.PathBuffer = undefined; + @memcpy(cwd_buf[0..options.cwd.len], options.cwd); + cwd_buf[options.cwd.len] = 0; + const cwd = cwd_buf[0..options.cwd.len :0]; uv_process_options.cwd = cwd.ptr; diff --git a/src/install/lifecycle_script_runner.zig b/src/install/lifecycle_script_runner.zig index f981c64152..0d1eeddef3 100644 --- a/src/install/lifecycle_script_runner.zig +++ b/src/install/lifecycle_script_runner.zig @@ -106,7 +106,7 @@ pub const LifecycleScriptSubprocess = struct { const manager = this.manager; const original_script = this.scripts.items[next_script_index].?; - const cwd = bun.path.z(this.scripts.cwd, &cwd_z_buf); + const cwd = this.scripts.cwd; const env = manager.env; this.stdout.setParent(this); this.stderr.setParent(this); diff --git a/src/install/lockfile.zig b/src/install/lockfile.zig index 8fcef43a64..d0e7115a6e 100644 --- a/src/install/lockfile.zig +++ b/src/install/lockfile.zig @@ -2767,7 +2767,7 @@ pub const Package = extern struct { items: [Lockfile.Scripts.names.len]?Lockfile.Scripts.Entry, first_index: u8, total: u8, - cwd: string, + cwd: stringZ, package_name: string, pub fn printScripts( @@ -2955,7 +2955,7 @@ pub const Package = extern struct { this: *const Package.Scripts, lockfile: *Lockfile, lockfile_buf: []const u8, - cwd: string, + cwd_: string, package_name: string, resolution_tag: Resolution.Tag, add_node_gyp_rebuild_script: bool, @@ -2963,11 +2963,26 @@ pub const Package = extern struct { const allocator = lockfile.allocator; const first_index, const total, const scripts = getScriptEntries(this, lockfile, lockfile_buf, resolution_tag, add_node_gyp_rebuild_script); if (first_index != -1) { + var cwd_buf: if (Environment.isWindows) bun.PathBuffer else void = undefined; + + const cwd = if (comptime !Environment.isWindows) + cwd_ + else brk: { + @memcpy(cwd_buf[0..cwd_.len], cwd_); + cwd_buf[cwd_.len] = 0; + const cwd_handle = bun.openDirNoRenamingOrDeletingWindows(bun.invalid_fd, cwd_buf[0..cwd_.len :0]) catch break :brk cwd_; + + var buf: bun.WPathBuffer = undefined; + const new_cwd = bun.windows.GetFinalPathNameByHandle(cwd_handle.fd, .{}, &buf) catch break :brk cwd_; + + break :brk strings.convertUTF16toUTF8InBuffer(&cwd_buf, new_cwd) catch break :brk cwd_; + }; + return .{ .items = scripts, .first_index = @intCast(first_index), .total = total, - .cwd = allocator.dupe(u8, cwd) catch bun.outOfMemory(), + .cwd = allocator.dupeZ(u8, cwd) catch bun.outOfMemory(), .package_name = package_name, }; } diff --git a/test/cli/install/bun-workspaces.test.ts b/test/cli/install/bun-workspaces.test.ts index 5093f6d48b..90ca47d7f4 100644 --- a/test/cli/install/bun-workspaces.test.ts +++ b/test/cli/install/bun-workspaces.test.ts @@ -484,3 +484,28 @@ for (const glob of [true, false]) { }); }); } + +test("cwd in workspace script is not the symlink path on windows", async () => { + await Promise.all([ + write( + join(packageDir, "package.json"), + JSON.stringify({ + name: "foo", + workspaces: ["pkg1"], + }), + ), + write( + join(packageDir, "pkg1", "package.json"), + JSON.stringify({ + name: "pkg1", + scripts: { + postinstall: 'bun -e \'require("fs").writeFileSync("cwd", process.cwd())\'', + }, + }), + ), + ]); + + await runBunInstall(env, packageDir); + + expect(await file(join(packageDir, "node_modules", "pkg1", "cwd")).text()).toBe(join(packageDir, "pkg1")); +});