diff options
Diffstat (limited to 'src/install/install.zig')
| -rw-r--r-- | src/install/install.zig | 133 |
1 files changed, 89 insertions, 44 deletions
diff --git a/src/install/install.zig b/src/install/install.zig index dad1c4f99..d56c4c3c5 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -4934,14 +4934,13 @@ pub const PackageManager = struct { return initMaybeInstall(ctx, package_json_file_, params, false); } - pub fn initMaybeInstall( + fn initMaybeInstall( ctx: Command.Context, package_json_file_: ?std.fs.File, comptime params: []const ParamType, comptime is_install: bool, ) !*PackageManager { - var _ctx = ctx; - var cli = try CommandLineArguments.parse(ctx.allocator, params, &_ctx); + const cli = try CommandLineArguments.parse(ctx.allocator, params); if (comptime is_install) { if (cli.positionals.len > 1) { @@ -4949,13 +4948,15 @@ pub const PackageManager = struct { } } - return try initWithCLI(_ctx, package_json_file_, cli); + var _ctx = ctx; + return initWithCLI(&_ctx, package_json_file_, cli, is_install); } - pub fn initWithCLI( - ctx: Command.Context, + fn initWithCLI( + ctx: *Command.Context, package_json_file_: ?std.fs.File, cli: CommandLineArguments, + comptime is_install: bool, ) !*PackageManager { // assume that spawning a thread will take a lil so we do that asap try HTTP.HTTPThread.init(); @@ -4970,7 +4971,7 @@ pub const PackageManager = struct { } var fs = try Fs.FileSystem.init(null); - var original_cwd = std.mem.trimRight(u8, fs.top_level_dir, "/"); + var original_cwd = strings.withoutTrailingSlash(fs.top_level_dir); bun.copy(u8, &cwd_buf, original_cwd); @@ -4978,41 +4979,93 @@ pub const PackageManager = struct { // // We will walk up from the cwd, calling chdir on each directory until we find a package.json // If we fail to find one, we will report an error saying no packages to install - var package_json_file: std.fs.File = undefined; - - 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", .{ .mode = .read_write }) catch brk: { - var this_cwd = original_cwd; - outer: while (std.fs.path.dirname(this_cwd)) |parent| { - cwd_buf[parent.len] = 0; - var chdir = cwd_buf[0..parent.len :0]; - - std.os.chdirZ(chdir) catch |err| { - Output.prettyErrorln("Error {s} while chdir - {s}", .{ @errorName(err), bun.span(chdir) }); + const package_json_file = package_json_file_ orelse brk: { + var this_cwd = original_cwd; + const child_json = child: { + while (true) { + var dir = std.fs.openDirAbsolute(this_cwd, .{}) catch |err| { + Output.prettyErrorln("Error {s} accessing {s}", .{ @errorName(err), this_cwd }); Output.flush(); return err; }; + defer dir.close(); + break :child dir.openFileZ("package.json", .{ .mode = .read_write }) catch { + if (std.fs.path.dirname(this_cwd)) |parent| { + this_cwd = parent; + continue; + } else { + break; + } + }; + } + return error.MissingPackageJSON; + }; - break :brk std.fs.cwd().openFileZ("package.json", .{ .mode = .read_write }) catch { + const child_cwd = this_cwd; + // Check if this is a workspace; if so, use root package + if (comptime is_install) { + var found = false; + while (std.fs.path.dirname(this_cwd)) |parent| { + var dir = std.fs.openDirAbsolute(parent, .{}) catch break; + defer dir.close(); + const json_file = dir.openFileZ("package.json", .{ .mode = .read_write }) catch { this_cwd = parent; - continue :outer; + continue; }; + defer if (!found) json_file.close(); + const json_stat = try json_file.stat(); + const json_buf = try ctx.allocator.alloc(u8, json_stat.size + 64); + defer ctx.allocator.free(json_buf); + const json_len = try json_file.preadAll(json_buf, 0); + var path_buf: [bun.MAX_PATH_BYTES]u8 = undefined; + const json_path = try bun.getFdPath(json_file.handle, &path_buf); + const json_source = logger.Source.initPathString( + json_path, + json_buf[0..json_len], + ); + initializeStore(); + const json = try json_parser.ParseJSONUTF8(&json_source, ctx.log, ctx.allocator); + if (json.asProperty("workspaces")) |prop| { + var workspace_names = bun.StringMap.init(ctx.allocator, true); + defer workspace_names.deinit(); + const json_array = switch (prop.expr.data) { + .e_array => |arr| arr, + .e_object => |obj| if (obj.get("packages")) |packages| switch (packages.data) { + .e_array => |arr| arr, + else => break, + } else break, + else => break, + }; + _ = Package.processWorkspaceNamesArray( + &workspace_names, + ctx.allocator, + ctx.log, + json_array, + &json_source, + prop.loc, + null, + ) catch break; + for (workspace_names.keys()) |path| { + if (strings.eql(child_cwd, path)) { + found = true; + child_json.close(); + fs.top_level_dir = parent; + break :brk json_file; + } + } + break; + } + this_cwd = parent; } + } - bun.copy(u8, &cwd_buf, original_cwd); - cwd_buf[original_cwd.len] = 0; - var real_cwd: [:0]u8 = cwd_buf[0..original_cwd.len :0]; - std.os.chdirZ(real_cwd) catch {}; - - return error.MissingPackageJSON; - }; - } + fs.top_level_dir = child_cwd; + break :brk child_json; + }; - fs.top_level_dir = try std.os.getcwd(&cwd_buf); + try std.os.chdir(fs.top_level_dir); + try BunArguments.loadConfig(ctx.allocator, cli.config, ctx, .InstallCommand); + bun.copy(u8, &cwd_buf, fs.top_level_dir); cwd_buf[fs.top_level_dir.len] = '/'; cwd_buf[fs.top_level_dir.len + 1] = 0; fs.top_level_dir = cwd_buf[0 .. fs.top_level_dir.len + 1]; @@ -5640,11 +5693,7 @@ pub const PackageManager = struct { } }; - pub fn parse( - allocator: std.mem.Allocator, - comptime params: []const ParamType, - ctx: *Command.Context, - ) !CommandLineArguments { + pub fn parse(allocator: std.mem.Allocator, comptime params: []const ParamType) !CommandLineArguments { var diag = clap.Diagnostic{}; var args = clap.parse(clap.Help, params, .{ @@ -5693,8 +5742,6 @@ pub const PackageManager = struct { cli.config = opt; } - try BunArguments.loadConfig(allocator, cli.config, ctx, .InstallCommand); - cli.link_native_bins = args.options("--link-native-bins"); if (comptime params.len == add_params.len) { @@ -6296,10 +6343,8 @@ pub const PackageManager = struct { var cwd_buf: [bun.MAX_PATH_BYTES]u8 = undefined; var package_json_cwd_buf: [bun.MAX_PATH_BYTES]u8 = undefined; - pub inline fn install( - ctx: Command.Context, - ) !void { - var manager = PackageManager.initMaybeInstall(ctx, null, &install_params, true) catch |err| { + pub inline fn install(ctx: Command.Context) !void { + var manager = initMaybeInstall(ctx, null, &install_params, true) catch |err| { if (err == error.SwitchToBunAdd) { return add(ctx); } |
