aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbun.lockbbin7340 -> 7340 bytes
-rw-r--r--src/api/schema.d.ts1
-rw-r--r--src/api/schema.js10
-rw-r--r--src/api/schema.peechy1
-rw-r--r--src/api/schema.zig10
-rw-r--r--src/bunfig.zig10
-rw-r--r--src/cli.zig12
-rw-r--r--src/install/bin.zig177
-rw-r--r--src/install/install.zig86
9 files changed, 273 insertions, 34 deletions
diff --git a/bun.lockb b/bun.lockb
index 88730849d..7aea3cceb 100755
--- a/bun.lockb
+++ b/bun.lockb
Binary files differ
diff --git a/src/api/schema.d.ts b/src/api/schema.d.ts
index d896bc160..6c667e455 100644
--- a/src/api/schema.d.ts
+++ b/src/api/schema.d.ts
@@ -632,6 +632,7 @@ export interface BunInstall {
native_bin_links?: string[];
disable_cache?: boolean;
disable_manifest_cache?: boolean;
+ global_dir?: string;
}
export declare function encodeStackFrame(
diff --git a/src/api/schema.js b/src/api/schema.js
index 67852d027..2a1fd8c1d 100644
--- a/src/api/schema.js
+++ b/src/api/schema.js
@@ -2902,6 +2902,10 @@ function decodeBunInstall(bb) {
result["disable_manifest_cache"] = !!bb.readByte();
break;
+ case 17:
+ result["global_dir"] = bb.readString();
+ break;
+
default:
throw new Error("Attempted to parse invalid message");
}
@@ -3010,6 +3014,12 @@ function encodeBunInstall(message, bb) {
bb.writeByte(16);
bb.writeByte(value);
}
+
+ var value = message["global_dir"];
+ if (value != null) {
+ bb.writeByte(17);
+ bb.writeString(value);
+ }
bb.writeByte(0);
}
diff --git a/src/api/schema.peechy b/src/api/schema.peechy
index a7284f713..59c239aa8 100644
--- a/src/api/schema.peechy
+++ b/src/api/schema.peechy
@@ -547,4 +547,5 @@ message BunInstall {
bool disable_cache = 15;
bool disable_manifest_cache = 16;
+ string global_dir = 17;
} \ No newline at end of file
diff --git a/src/api/schema.zig b/src/api/schema.zig
index 8879b34cb..e12eda9d5 100644
--- a/src/api/schema.zig
+++ b/src/api/schema.zig
@@ -2719,6 +2719,9 @@ pub const Api = struct {
/// disable_manifest_cache
disable_manifest_cache: ?bool = null,
+ /// global_dir
+ global_dir: ?[]const u8 = null,
+
pub fn decode(reader: anytype) anyerror!BunInstall {
var this = std.mem.zeroes(BunInstall);
@@ -2776,6 +2779,9 @@ pub const Api = struct {
16 => {
this.disable_manifest_cache = try reader.readValue(bool);
},
+ 17 => {
+ this.global_dir = try reader.readValue([]const u8);
+ },
else => {
return error.InvalidMessage;
},
@@ -2849,6 +2855,10 @@ pub const Api = struct {
try writer.writeFieldID(16);
try writer.writeInt(@as(u8, @boolToInt(disable_manifest_cache)));
}
+ if (this.global_dir) |global_dir| {
+ try writer.writeFieldID(17);
+ try writer.writeValue(@TypeOf(global_dir), global_dir);
+ }
try writer.endMessage();
}
};
diff --git a/src/bunfig.zig b/src/bunfig.zig
index 65e200098..78aed4761 100644
--- a/src/bunfig.zig
+++ b/src/bunfig.zig
@@ -237,7 +237,7 @@ pub const Bunfig = struct {
}
if (bun.get("lockfile")) |lockfile_expr| {
- if (lockfile_expr.get("outputFormat")) |lockfile| {
+ if (lockfile_expr.get("print")) |lockfile| {
try this.expect(lockfile, .e_string);
if (lockfile.asString(this.allocator)) |value| {
if (!(strings.eqlComptime(value, "bun"))) {
@@ -287,6 +287,12 @@ pub const Bunfig = struct {
}
}
+ if (bun.get("globalDir")) |dir| {
+ if (dir.asString()) |value| {
+ install.global_dir = value;
+ }
+ }
+
if (bun.get("logLevel")) |expr| {
try this.loadLogLevel(expr);
}
@@ -320,7 +326,7 @@ pub const Bunfig = struct {
}
}
- if (cache.get("directory")) |directory| {
+ if (cache.get("dir")) |directory| {
if (directory.asString(allocator)) |value| {
install.cache_directory = value;
}
diff --git a/src/cli.zig b/src/cli.zig
index ed588a2cd..f00c0b5a8 100644
--- a/src/cli.zig
+++ b/src/cli.zig
@@ -795,7 +795,16 @@ pub const Command = struct {
RootCommandMatcher.case("completions") => .InstallCompletionsCommand,
RootCommandMatcher.case("getcompletes") => .GetCompletionsCommand,
- RootCommandMatcher.case("i"), RootCommandMatcher.case("install") => .InstallCommand,
+ RootCommandMatcher.case("i"), RootCommandMatcher.case("install") => brk: {
+ for (args_iter.buf) |arg| {
+ const span = std.mem.span(arg);
+ if (span.len > 0 and (strings.eqlComptime(span, "-g") or strings.eqlComptime(span, "--global"))) {
+ break :brk Command.Tag.AddCommand;
+ }
+ }
+
+ break :brk Command.Tag.InstallCommand;
+ },
RootCommandMatcher.case("c"), RootCommandMatcher.case("create") => .CreateCommand,
RootCommandMatcher.case(TestCommand.name) => .TestCommand,
@@ -836,6 +845,7 @@ pub const Command = struct {
pub fn start(allocator: std.mem.Allocator, log: *logger.Log) !void {
const tag = which();
+
switch (tag) {
.DiscordCommand => return try DiscordCommand.exec(allocator),
.HelpCommand => return try HelpCommand.exec(allocator),
diff --git a/src/install/bin.zig b/src/install/bin.zig
index 810009be3..15e768bca 100644
--- a/src/install/bin.zig
+++ b/src/install/bin.zig
@@ -7,6 +7,9 @@ const strings = @import("strings");
const Environment = @import("../env.zig");
const Path = @import("../resolver/resolve_path.zig");
const C = @import("../c.zig");
+const Fs = @import("../fs.zig");
+const stringZ = @import("../global.zig").stringZ;
+
/// Normalized `bin` field in [package.json](https://docs.npmjs.com/cli/v8/configuring-npm/package-json#bin)
/// Can be a:
/// - file path (relative to the package root)
@@ -130,6 +133,8 @@ pub const Bin = extern struct {
/// Used for generating relative paths
package_name: strings.StringOrTinyString,
+ global_bin_dir: stringZ = "",
+
string_buf: []const u8,
err: ?anyerror = null,
@@ -159,14 +164,14 @@ pub const Bin = extern struct {
// 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
pub fn link(this: *Linker) void {
- var from_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
- var path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
+ var target_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
+ var dest_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
- from_buf[0..".bin/".len].* = ".bin/".*;
- var from_remain: []u8 = from_buf[".bin/".len..];
- path_buf[0.."../".len].* = "../".*;
+ target_buf[0..".bin/".len].* = ".bin/".*;
+ var from_remain: []u8 = target_buf[".bin/".len..];
+ dest_buf[0.."../".len].* = "../".*;
- var remain: []u8 = path_buf["../".len..];
+ var remain: []u8 = dest_buf["../".len..];
const name = this.package_name.slice();
std.mem.copy(u8, remain, name);
remain = remain[name.len..];
@@ -192,17 +197,17 @@ pub const Bin = extern struct {
std.mem.copy(u8, remain, target);
remain = remain[target.len..];
remain[0] = 0;
- const target_len = @ptrToInt(remain.ptr) - @ptrToInt(&path_buf);
+ const target_len = @ptrToInt(remain.ptr) - @ptrToInt(&dest_buf);
remain = remain[1..];
- var target_path: [:0]u8 = path_buf[0..target_len :0];
+ var target_path: [:0]u8 = dest_buf[0..target_len :0];
// we need to use the unscoped package name here
// this is why @babel/parser would fail to link
const unscoped_name = unscopedPackageName(name);
std.mem.copy(u8, from_remain, unscoped_name);
from_remain = from_remain[unscoped_name.len..];
from_remain[0] = 0;
- var dest_path: [:0]u8 = from_buf[0 .. @ptrToInt(from_remain.ptr) - @ptrToInt(&from_buf) :0];
+ var dest_path: [:0]u8 = target_buf[0 .. @ptrToInt(from_remain.ptr) - @ptrToInt(&target_buf) :0];
std.os.symlinkatZ(target_path, this.root_node_modules_folder, dest_path) catch |err| {
// Silently ignore PathAlreadyExists
@@ -224,15 +229,15 @@ pub const Bin = extern struct {
std.mem.copy(u8, remain, target);
remain = remain[target.len..];
remain[0] = 0;
- const target_len = @ptrToInt(remain.ptr) - @ptrToInt(&path_buf);
+ const target_len = @ptrToInt(remain.ptr) - @ptrToInt(&dest_buf);
remain = remain[1..];
- var target_path: [:0]u8 = path_buf[0..target_len :0];
+ var target_path: [:0]u8 = dest_buf[0..target_len :0];
var name_to_use = this.bin.value.named_file[0].slice(this.string_buf);
std.mem.copy(u8, from_remain, name_to_use);
from_remain = from_remain[name_to_use.len..];
from_remain[0] = 0;
- var dest_path: [:0]u8 = from_buf[0 .. @ptrToInt(from_remain.ptr) - @ptrToInt(&from_buf) :0];
+ var dest_path: [:0]u8 = target_buf[0 .. @ptrToInt(from_remain.ptr) - @ptrToInt(&target_buf) :0];
std.os.symlinkatZ(target_path, this.root_node_modules_folder, dest_path) catch |err| {
// Silently ignore PathAlreadyExists
@@ -257,9 +262,9 @@ pub const Bin = extern struct {
remain[0] = 0;
var dir = std.fs.Dir{ .fd = this.package_installed_node_modules };
- var joined = Path.joinStringBuf(&from_buf, &parts, .auto);
- from_buf[joined.len] = 0;
- var joined_: [:0]u8 = from_buf[0..joined.len :0];
+ var joined = Path.joinStringBuf(&target_buf, &parts, .auto);
+ target_buf[joined.len] = 0;
+ var joined_: [:0]u8 = target_buf[0..joined.len :0];
var child_dir = dir.openDirZ(joined_, .{ .iterate = true }) catch |err| {
this.err = err;
return;
@@ -268,22 +273,22 @@ pub const Bin = extern struct {
var iter = child_dir.iterate();
- var basedir_path = std.os.getFdPath(child_dir.fd, &from_buf) catch |err| {
+ var basedir_path = std.os.getFdPath(child_dir.fd, &target_buf) catch |err| {
this.err = err;
return;
};
- from_buf[basedir_path.len] = std.fs.path.sep;
- var from_buf_remain = from_buf[basedir_path.len + 1 ..];
+ target_buf[basedir_path.len] = std.fs.path.sep;
+ var target_buf_remain = target_buf[basedir_path.len + 1 ..];
while (iter.next() catch null) |entry_| {
const entry: std.fs.Dir.Entry = entry_;
switch (entry.kind) {
std.fs.Dir.Entry.Kind.SymLink, std.fs.Dir.Entry.Kind.File => {
- std.mem.copy(u8, from_buf_remain, entry.name);
- from_buf_remain = from_buf_remain[entry.name.len..];
- from_buf_remain[0] = 0;
- var from_path: [:0]u8 = from_buf[0 .. @ptrToInt(from_buf_remain.ptr) - @ptrToInt(&from_buf) :0];
- var to_path = std.fmt.bufPrintZ(&path_buf, ".bin/{s}", .{entry.name}) catch unreachable;
+ std.mem.copy(u8, target_buf_remain, entry.name);
+ target_buf_remain = target_buf_remain[entry.name.len..];
+ 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 = std.fmt.bufPrintZ(&dest_buf, ".bin/{s}", .{entry.name}) catch unreachable;
std.os.symlinkatZ(
from_path,
@@ -312,5 +317,131 @@ pub const Bin = extern struct {
},
}
}
+
+ // fn linkGlobalSymlink(this: *Linker, realpath: string, filename_in_terminal: string) void {}
+
+ // pub fn linkGlobal(this: *Linker) void {
+ // var target_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
+ // const name = this.package_name.slice();
+
+ // if (comptime Environment.isWindows) {
+ // @compileError("Bin.Linker.link() needs to be updated to generate .cmd files on Windows");
+ // }
+
+ // switch (this.bin.tag) {
+ // .none => {
+ // if (comptime Environment.isDebug) {
+ // unreachable;
+ // }
+ // },
+ // .file => {
+ // var target = this.bin.value.file.slice(this.string_buf);
+
+ // if (strings.hasPrefix(target, "./")) {
+ // target = target[2..];
+ // }
+ // @memcpy(&target_buf, target.ptr, target.len);
+
+ // // we need to use the unscoped package name here
+ // // this is why @babel/parser would fail to link
+ // const unscoped_name = unscopedPackageName(name);
+
+ // },
+ // .named_file => {
+ // var target = this.bin.value.named_file[1].slice(this.string_buf);
+ // if (strings.hasPrefix(target, "./")) {
+ // target = target[2..];
+ // }
+ // std.mem.copy(u8, remain, target);
+ // remain = remain[target.len..];
+ // remain[0] = 0;
+ // const target_len = @ptrToInt(remain.ptr) - @ptrToInt(&dest_buf);
+ // remain = remain[1..];
+
+ // var target_path: [:0]u8 = dest_buf[0..target_len :0];
+ // var name_to_use = this.bin.value.named_file[0].slice(this.string_buf);
+ // std.mem.copy(u8, from_remain, name_to_use);
+ // from_remain = from_remain[name_to_use.len..];
+ // from_remain[0] = 0;
+ // var dest_path: [:0]u8 = target_buf[0 .. @ptrToInt(from_remain.ptr) - @ptrToInt(&target_buf) :0];
+
+ // std.os.symlinkatZ(target_path, this.root_node_modules_folder, dest_path) catch |err| {
+ // // Silently ignore PathAlreadyExists
+ // // Most likely, the symlink was already created by another package
+ // if (err == error.PathAlreadyExists) {
+ // this.setPermissions(dest_path);
+ // return;
+ // }
+
+ // this.err = err;
+ // };
+ // this.setPermissions(dest_path);
+ // },
+ // .dir => {
+ // var target = this.bin.value.dir.slice(this.string_buf);
+ // var parts = [_][]const u8{ name, target };
+ // if (strings.hasPrefix(target, "./")) {
+ // target = target[2..];
+ // }
+ // std.mem.copy(u8, remain, target);
+ // remain = remain[target.len..];
+ // remain[0] = 0;
+ // var dir = std.fs.Dir{ .fd = this.package_installed_node_modules };
+
+ // var joined = Path.joinStringBuf(&target_buf, &parts, .auto);
+ // target_buf[joined.len] = 0;
+ // var joined_: [:0]u8 = target_buf[0..joined.len :0];
+ // var child_dir = dir.openDirZ(joined_, .{ .iterate = true }) catch |err| {
+ // this.err = err;
+ // return;
+ // };
+ // defer child_dir.close();
+
+ // var iter = child_dir.iterate();
+
+ // var basedir_path = std.os.getFdPath(child_dir.fd, &target_buf) catch |err| {
+ // this.err = err;
+ // return;
+ // };
+ // target_buf[basedir_path.len] = std.fs.path.sep;
+ // var target_buf_remain = target_buf[basedir_path.len + 1 ..];
+
+ // while (iter.next() catch null) |entry_| {
+ // const entry: std.fs.Dir.Entry = entry_;
+ // switch (entry.kind) {
+ // std.fs.Dir.Entry.Kind.SymLink, std.fs.Dir.Entry.Kind.File => {
+ // std.mem.copy(u8, target_buf_remain, entry.name);
+ // target_buf_remain = target_buf_remain[entry.name.len..];
+ // 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 = std.fmt.bufPrintZ(&dest_buf, ".bin/{s}", .{entry.name}) catch unreachable;
+
+ // std.os.symlinkatZ(
+ // from_path,
+ // this.root_node_modules_folder,
+ // to_path,
+ // ) catch |err| {
+
+ // // Silently ignore PathAlreadyExists
+ // // Most likely, the symlink was already created by another package
+ // if (err == error.PathAlreadyExists) {
+ // this.setPermissions(to_path);
+ // continue;
+ // }
+
+ // this.err = err;
+ // continue;
+ // };
+ // this.setPermissions(to_path);
+ // },
+ // else => {},
+ // }
+ // }
+ // },
+ // .map => {
+ // this.err = error.NotImplementedYet;
+ // },
+ // }
+ // }
};
};
diff --git a/src/install/install.zig b/src/install/install.zig
index facdf9faf..8eeebb752 100644
--- a/src/install/install.zig
+++ b/src/install/install.zig
@@ -21,7 +21,7 @@ const linker = @import("../linker.zig");
const panicky = @import("../panic_handler.zig");
const sync = @import("../sync.zig");
const Api = @import("../api/schema.zig").Api;
-const resolve_path = @import("../resolver/resolve_path.zig");
+const Path = @import("../resolver/resolve_path.zig");
const configureTransformOptionsForBun = @import("../javascript/jsc/config.zig").configureTransformOptionsForBun;
const Command = @import("../cli.zig").Command;
const bundler = @import("../bundler.zig");
@@ -1090,7 +1090,7 @@ pub const Lockfile = struct {
if (!std.fs.path.isAbsolute(lockfile_path_)) {
var cwd = try std.os.getcwd(&lockfile_path_buf1);
var parts = [_]string{lockfile_path_};
- var lockfile_path__ = resolve_path.joinAbsStringBuf(cwd, &lockfile_path_buf2, &parts, .auto);
+ var lockfile_path__ = Path.joinAbsStringBuf(cwd, &lockfile_path_buf2, &parts, .auto);
lockfile_path_buf2[lockfile_path__.len] = 0;
lockfile_path = lockfile_path_buf2[0..lockfile_path__.len :0];
} else {
@@ -3874,7 +3874,7 @@ pub const PackageManager = struct {
};
continue :brk;
}
- Output.prettyErrorln("<r><red>error<r>: {s} accessing temporary directory. Please set <b>$BUN_TMPDIR<r> or <b>$BUN_INSTALL_DIR<r>", .{
+ Output.prettyErrorln("<r><red>error<r>: {s} accessing temporary directory. Please set <b>$BUN_TMPDIR<r> or <b>$BUN_INSTALL<r>", .{
@errorName(err2),
});
Output.flush();
@@ -3892,7 +3892,7 @@ pub const PackageManager = struct {
continue :brk;
}
- Output.prettyErrorln("<r><red>error<r>: {s} accessing temporary directory. Please set <b>$BUN_TMPDIR<r> or <b>$BUN_INSTALL_DIR<r>", .{
+ Output.prettyErrorln("<r><red>error<r>: {s} accessing temporary directory. Please set <b>$BUN_TMPDIR<r> or <b>$BUN_INSTALL<r>", .{
@errorName(err),
});
Output.flush();
@@ -4907,6 +4907,11 @@ pub const PackageManager = struct {
pub const Options = struct {
log_level: LogLevel = LogLevel.default,
+ global: bool = false,
+
+ /// destination directory to link bins into
+ // must be a variable due to global installs and bunx
+ bin_path: stringZ = "node_modules/.bin",
lockfile_path: stringZ = Lockfile.default_filename,
save_lockfile_path: stringZ = Lockfile.default_filename,
@@ -4982,6 +4987,36 @@ pub const PackageManager = struct {
optional: bool = false,
};
+ pub fn openGlobalDir(opts_: ?*Api.BunInstall) !std.fs.Dir {
+ if (std.os.getenvZ("BUN_INSTALL_GLOBAL_DIR")) |home_dir| {
+ return try std.fs.cwd().makeOpenPath(home_dir, .{ .iterate = true });
+ }
+
+ if (opts_) |opts| {
+ if (opts.global_dir) |home_dir| {
+ if (home_dir.len > 0) {
+ return try std.fs.cwd().makeOpenPath(home_dir, .{ .iterate = true });
+ }
+ }
+ }
+
+ if (std.os.getenvZ("BUN_INSTALL")) |home_dir| {
+ var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
+ var parts = [_]string{ "install", "global" };
+ var path = Path.joinAbsStringBuf(home_dir, &buf, &parts, .auto);
+ return try std.fs.cwd().makeOpenPath(path, .{ .iterate = true });
+ }
+
+ if (std.os.getenvZ("XDG_CACHE_HOME") orelse std.os.getenvZ("HOME")) |home_dir| {
+ var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
+ var parts = [_]string{ "./bun", "install", "global" };
+ var path = Path.joinAbsStringBuf(home_dir, &buf, &parts, .auto);
+ return try std.fs.cwd().makeOpenPath(path, .{ .iterate = true });
+ }
+
+ return error.@"No global directory found";
+ }
+
pub fn load(
this: *Options,
allocator: std.mem.Allocator,
@@ -5502,10 +5537,22 @@ pub const PackageManager = struct {
package_json_file_: ?std.fs.File,
comptime params: []const ParamType,
) !*PackageManager {
+ var cli = try CommandLineArguments.parse(ctx.allocator, params);
+ return try initWithCLI(ctx, package_json_file_, cli);
+ }
+
+ fn initWithCLI(
+ ctx: Command.Context,
+ package_json_file_: ?std.fs.File,
+ cli: CommandLineArguments,
+ ) !*PackageManager {
// assume that spawning a thread will take a lil so we do that asap
try NetworkThread.warmup();
- var cli = try CommandLineArguments.parse(ctx.allocator, params);
+ if (cli.global) {
+ var global_dir = try Options.openGlobalDir(ctx.install);
+ try global_dir.setAsCwd();
+ }
var fs = try Fs.FileSystem.init1(ctx.allocator, null);
var original_cwd = std.mem.trimRight(u8, fs.top_level_dir, "/");
@@ -5521,6 +5568,7 @@ pub const PackageManager = struct {
if (package_json_file_) |file| {
package_json_file = file;
} else {
+
// can't use orelse due to a stage1 bug
package_json_file = std.fs.cwd().openFileZ("package.json", .{ .read = true, .write = true }) catch brk: {
var this_cwd = original_cwd;
@@ -5664,6 +5712,7 @@ pub const PackageManager = struct {
clap.parseParam("--no-cache Ignore manifest cache entirely") catch unreachable,
clap.parseParam("--silent Don't log anything") catch unreachable,
clap.parseParam("--verbose Excessively verbose logging") catch unreachable,
+ clap.parseParam("-g, --global Install globally") catch unreachable,
clap.parseParam("--cwd <STR> Set a specific cwd") catch unreachable,
clap.parseParam("--backend <STR> Platform-specific optimizations for installing dependencies. For macOS, \"clonefile\" (default), \"copyfile\"") catch unreachable,
clap.parseParam("--link-native-bins <STR>... Link \"bin\" from a matching platform-specific \"optionalDependencies\" instead. Default: esbuild, turbo") catch unreachable,
@@ -5693,6 +5742,7 @@ pub const PackageManager = struct {
cache_dir: string = "",
lockfile: string = "",
token: string = "",
+ global: bool = false,
backend: ?PackageInstall.Method = null,
@@ -5760,6 +5810,7 @@ pub const PackageManager = struct {
cli.production = args.flag("--production");
cli.no_save = args.flag("--no-save");
cli.dry_run = args.flag("--dry-run");
+ cli.global = args.flag("--global");
cli.force = args.flag("--force");
// cli.no_dedupe = args.flag("--no-dedupe");
cli.no_cache = args.flag("--no-cache");
@@ -5798,7 +5849,7 @@ pub const PackageManager = struct {
if (cwd_.len > 0 and cwd_[0] == '.') {
var cwd = try std.os.getcwd(&buf);
var parts = [_]string{cwd_};
- var path_ = resolve_path.joinAbsStringBuf(cwd, &buf2, &parts, .auto);
+ var path_ = Path.joinAbsStringBuf(cwd, &buf2, &parts, .auto);
buf2[path_.len] = 0;
final_path = buf2[0..path_.len :0];
} else {
@@ -6272,7 +6323,7 @@ pub const PackageManager = struct {
// This is where we clean dangling symlinks
// This could be slow if there are a lot of symlinks
- if (cwd.openDirZ("node_modules/.bin", .{
+ if (cwd.openDirZ(manager.options.bin_path, .{
.iterate = true,
})) |node_modules_bin_| {
var node_modules_bin: std.fs.Dir = node_modules_bin_;
@@ -6456,6 +6507,8 @@ pub const PackageManager = struct {
var bin_linker = Bin.Linker{
.bin = bin,
.package_installed_node_modules = this.node_modules_folder.fd,
+ .global_bin_dir = this.manager.options.bin_path,
+ // .destination_dir_subpath = destination_dir_subpath,
.root_node_modules_folder = this.root_node_modules_folder.fd,
.package_name = strings.StringOrTinyString.init(name),
.string_buf = buf,
@@ -6500,7 +6553,7 @@ pub const PackageManager = struct {
if (this.manager.generateNetworkTaskForTarball(task_id, this.lockfile.packages.get(package_id)) catch unreachable) |task| {
task.schedule(&this.manager.network_tarball_batch);
- if (this.manager.network_tarball_batch.len > 6) {
+ if (this.manager.network_tarball_batch.len > 0) {
_ = this.manager.scheduleNetworkTasks();
}
}
@@ -6774,6 +6827,7 @@ pub const PackageManager = struct {
.bin = original_bin,
.package_installed_node_modules = folder.fd,
.root_node_modules_folder = node_modules_folder.fd,
+ .global_bin_dir = installer.manager.options.bin_path,
.package_name = strings.StringOrTinyString.init(name),
.string_buf = lockfile.buffers.string_bytes.items,
};
@@ -6935,6 +6989,14 @@ pub const PackageManager = struct {
const sum = manager.summary.add + manager.summary.remove + manager.summary.update;
had_any_diffs = had_any_diffs or sum > 0;
+ if (manager.options.enable.frozen_lockfile and had_any_diffs) {
+ if (log_level != .silent) {
+ Output.prettyErrorln("<r><red>error<r>: Lockfile had changes, but lockfile is frozen", .{});
+ }
+
+ Global.exit(1);
+ }
+
// If you changed packages, we will copy over the new package from the new lockfile
const new_dependencies = maybe_root.dependencies.get(lockfile.buffers.dependencies.items);
@@ -7013,6 +7075,14 @@ pub const PackageManager = struct {
root = Lockfile.Package{};
try manager.lockfile.initEmpty(ctx.allocator);
+ if (manager.options.enable.frozen_lockfile) {
+ if (log_level != .silent) {
+ Output.prettyErrorln("<r><red>error<r>: Lockfile had changes, but lockfile is frozen", .{});
+ }
+
+ Global.exit(1);
+ }
+
try Lockfile.Package.parseMain(
manager.lockfile,
&root,