diff options
-rw-r--r-- | src/install/bin.zig | 31 | ||||
-rw-r--r-- | src/install/install.zig | 4 | ||||
-rw-r--r-- | test/bun.js/install/bun-install.test.ts | 2 |
3 files changed, 21 insertions, 16 deletions
diff --git a/src/install/bin.zig b/src/install/bin.zig index 2d1113556..dfd29c927 100644 --- a/src/install/bin.zig +++ b/src/install/bin.zig @@ -257,7 +257,6 @@ pub const Bin = extern struct { pub const Linker = struct { bin: Bin, - package_installed_path: stringZ = "", package_installed_node_modules: std.os.fd_t = std.math.maxInt(std.os.fd_t), root_node_modules_folder: std.os.fd_t = std.math.maxInt(std.os.fd_t), @@ -309,6 +308,8 @@ pub const Bin = extern struct { setPermissions(this.root_node_modules_folder, dest_path); } + const dot_bin = ".bin" ++ std.fs.path.sep_str; + // It is important that we use symlinkat(2) with relative paths instead of symlink() // That way, if you move your node_modules folder around, the symlinks in .bin still work // If we used absolute paths for the symlinks, you'd end up with broken symlinks @@ -319,14 +320,22 @@ pub const Bin = extern struct { var remain: []u8 = &dest_buf; if (!link_global) { - target_buf[0..".bin/".len].* = ".bin/".*; - from_remain = target_buf[".bin/".len..]; - dest_buf[0.."..".len].* = "..".*; - remain = dest_buf["..".len..]; - std.mem.copy(u8, remain, this.package_installed_path); - remain = remain[this.package_installed_path.len..]; + const root_dir = std.fs.Dir{ .fd = this.root_node_modules_folder }; + const from = root_dir.realpath(dot_bin, &target_buf) catch |err| { + this.err = err; + return; + }; + const to = bun.getFdPath(this.package_installed_node_modules, &dest_buf) catch |err| { + this.err = err; + return; + }; + const rel = Path.relative(from, to); + std.mem.copy(u8, remain, rel); + remain = remain[rel.len..]; remain[0] = std.fs.path.sep; remain = remain[1..]; + from_remain[0..dot_bin.len].* = dot_bin.*; + from_remain = from_remain[dot_bin.len..]; } else { if (this.global_bin_dir.fd >= std.math.maxInt(std.os.fd_t)) { this.err = error.MissingGlobalBinDir; @@ -480,7 +489,7 @@ pub const Bin = extern struct { target_buf_remain[0] = 0; var from_path: [:0]u8 = target_buf[0 .. @ptrToInt(target_buf_remain.ptr) - @ptrToInt(&target_buf) :0]; var to_path = if (!link_global) - std.fmt.bufPrintZ(&dest_buf, ".bin/{s}", .{entry.name}) catch continue + std.fmt.bufPrintZ(&dest_buf, dot_bin ++ "{s}", .{entry.name}) catch continue else std.fmt.bufPrintZ(&dest_buf, "{s}", .{entry.name}) catch continue; @@ -500,8 +509,8 @@ pub const Bin = extern struct { var remain: []u8 = &dest_buf; if (!link_global) { - target_buf[0..".bin/".len].* = ".bin/".*; - from_remain = target_buf[".bin/".len..]; + target_buf[0..dot_bin.len].* = dot_bin.*; + from_remain = target_buf[dot_bin.len..]; dest_buf[0.."../".len].* = "../".*; remain = dest_buf["../".len..]; } else { @@ -631,7 +640,7 @@ pub const Bin = extern struct { target_buf_remain = target_buf_remain[entry.name.len..]; target_buf_remain[0] = 0; var to_path = if (!link_global) - std.fmt.bufPrintZ(&dest_buf, ".bin/{s}", .{entry.name}) catch continue + std.fmt.bufPrintZ(&dest_buf, dot_bin ++ "{s}", .{entry.name}) catch continue else std.fmt.bufPrintZ(&dest_buf, "{s}", .{entry.name}) catch continue; diff --git a/src/install/install.zig b/src/install/install.zig index ee46ad079..7bc79b015 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -5708,7 +5708,6 @@ pub const PackageManager = struct { manager: *PackageManager, lockfile: *Lockfile, progress: *std.Progress, - node_modules_path: stringZ, node_modules_folder: std.fs.IterableDir, skip_verify_installed_version_number: bool, skip_delete: bool, @@ -5928,7 +5927,6 @@ pub const PackageManager = struct { var bin_linker = Bin.Linker{ .bin = bin, - .package_installed_path = this.node_modules_path["node_modules".len..], .package_installed_node_modules = this.node_modules_folder.dir.fd, .global_bin_path = this.options.bin_path, .global_bin_dir = this.options.global_bin_dir.dir, @@ -6186,7 +6184,6 @@ pub const PackageManager = struct { .resolutions = resolutions, .lockfile = lockfile, .node = &install_node, - .node_modules_path = "node_modules", .node_modules_folder = node_modules_folder, .progress = progress, .skip_verify_installed_version_number = skip_verify_installed_version_number, @@ -6208,7 +6205,6 @@ pub const PackageManager = struct { // We deliberately do not close this folder. // If the package hasn't been downloaded, we will need to install it later // We use this file descriptor to know where to put it. - installer.node_modules_path = node_modules.relative_path; installer.node_modules_folder = try cwd.openIterableDir(node_modules.relative_path, .{}); var remaining = node_modules.dependencies; diff --git a/test/bun.js/install/bun-install.test.ts b/test/bun.js/install/bun-install.test.ts index a47bbd2ce..7de46869f 100644 --- a/test/bun.js/install/bun-install.test.ts +++ b/test/bun.js/install/bun-install.test.ts @@ -1764,7 +1764,7 @@ it("should consider peerDependencies during hoisting", async () => { expect(await readdirSorted(join(package_dir, "node_modules", ".bin"))).toEqual(["baz-exec", "baz-run"]); expect(await readlink(join(package_dir, "node_modules", ".bin", "baz-exec"))).toBe(join("..", "baz", "index.js")); expect(await readlink(join(package_dir, "node_modules", ".bin", "baz-run"))).toBe( - join("..", "bar", "node_modules", "baz", "index.js"), + join("..", "..", "bar", "node_modules", "baz", "index.js"), ); expect(await readlink(join(package_dir, "node_modules", "bar"))).toBe(join("..", "bar")); expect(await readdirSorted(join(package_dir, "bar"))).toEqual(["node_modules", "package.json"]); |