diff options
Diffstat (limited to 'src/install/install.zig')
-rw-r--r-- | src/install/install.zig | 172 |
1 files changed, 88 insertions, 84 deletions
diff --git a/src/install/install.zig b/src/install/install.zig index 5e1b54aa6..38f2ae11f 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -1641,6 +1641,7 @@ pub const PackageManager = struct { root_download_node: std.Progress.Node = undefined, to_remove: []const UpdateRequest = &[_]UpdateRequest{}, + to_update: bool = false, root_package_json_file: std.fs.File, root_dependency_list: Lockfile.DependencySlice = .{}, @@ -3821,9 +3822,9 @@ pub const PackageManager = struct { }, } } - for (manager.package_json_updates) |*update| { - if (strings.eql(update.name, name.slice())) { - update.failed = true; + for (manager.package_json_updates) |*request| { + if (strings.eql(request.name, name.slice())) { + request.failed = true; manager.options.do.save_lockfile = false; manager.options.do.save_yarn_lock = false; manager.options.do.install_packages = false; @@ -4880,21 +4881,21 @@ pub const PackageManager = struct { // 3. There is a "dependencies" (or equivalent list), and the package name exists in multiple lists ast_modifier: { // Try to use the existing spot in the dependencies list if possible - for (updates) |*update| { + for (updates) |*request| { inline for ([_]string{ "dependencies", "devDependencies", "optionalDependencies" }) |list| { if (current_package_json.asProperty(list)) |query| { if (query.expr.data == .e_object) { if (query.expr.asProperty( - if (update.is_aliased) - update.name + if (request.is_aliased) + request.name else - update.version.literal.slice(update.version_buf), + request.version.literal.slice(request.version_buf), )) |value| { if (value.expr.data == .e_string) { - if (!update.resolved_name.isEmpty() and strings.eql(list, dependency_list)) { + if (!request.resolved_name.isEmpty() and strings.eql(list, dependency_list)) { replacing += 1; } else { - update.e_string = value.expr.data.e_string; + request.e_string = value.expr.data.e_string; remaining -= 1; } } @@ -4919,16 +4920,16 @@ pub const PackageManager = struct { bun.copy(G.Property, new_dependencies, dependencies); @memset(new_dependencies[dependencies.len..], G.Property{}); - outer: for (updates) |*update| { - if (update.e_string != null) continue; - defer if (comptime Environment.allow_assert) std.debug.assert(update.e_string != null); + outer: for (updates) |*request| { + if (request.e_string != null) continue; + defer if (comptime Environment.allow_assert) std.debug.assert(request.e_string != null); var k: usize = 0; while (k < new_dependencies.len) : (k += 1) { if (new_dependencies[k].key) |key| { - if (!update.is_aliased and !update.resolved_name.isEmpty() and key.data.e_string.eql( + if (!request.is_aliased and !request.resolved_name.isEmpty() and key.data.e_string.eql( string, - update.resolved_name.slice(update.version_buf), + request.resolved_name.slice(request.version_buf), )) { // This actually is a duplicate which we did not // pick up before dependency resolution. @@ -4943,12 +4944,12 @@ pub const PackageManager = struct { } if (key.data.e_string.eql( string, - if (update.is_aliased) - update.name + if (request.is_aliased) + request.name else - update.version.literal.slice(update.version_buf), + request.version.literal.slice(request.version_buf), )) { - if (update.resolved_name.isEmpty()) { + if (request.resolved_name.isEmpty()) { // This actually is a duplicate like "react" // appearing in both "dependencies" and "optionalDependencies". // For this case, we'll just swap remove it @@ -4968,12 +4969,12 @@ pub const PackageManager = struct { new_dependencies[k].key = try JSAst.Expr.init( JSAst.E.String, JSAst.E.String{ - .data = try allocator.dupe(u8, if (update.is_aliased) - update.name - else if (update.resolved_name.isEmpty()) - update.version.literal.slice(update.version_buf) + .data = try allocator.dupe(u8, if (request.is_aliased) + request.name + else if (request.resolved_name.isEmpty()) + request.version.literal.slice(request.version_buf) else - update.resolved_name.slice(update.version_buf)), + request.resolved_name.slice(request.version_buf)), }, logger.Loc.Empty, ).clone(allocator); @@ -4986,8 +4987,8 @@ pub const PackageManager = struct { }, logger.Loc.Empty, ).clone(allocator); - update.e_string = new_dependencies[k].value.?.data.e_string; - if (update.is_aliased) continue :outer; + request.e_string = new_dependencies[k].value.?.data.e_string; + if (request.is_aliased) continue :outer; } } } @@ -5051,26 +5052,26 @@ pub const PackageManager = struct { } } - for (updates) |*update| { - if (update.e_string) |e_string| { - e_string.data = switch (update.resolution.tag) { - .npm => if (update.version.tag == .dist_tag and update.version.literal.isEmpty()) + for (updates) |*request| { + if (request.e_string) |e_string| { + e_string.data = switch (request.resolution.tag) { + .npm => if (request.version.tag == .dist_tag and request.version.literal.isEmpty()) switch (exact_versions) { false => std.fmt.allocPrint(allocator, "^{}", .{ - update.resolution.value.npm.version.fmt(update.version_buf), + request.resolution.value.npm.version.fmt(request.version_buf), }) catch unreachable, true => std.fmt.allocPrint(allocator, "{}", .{ - update.resolution.value.npm.version.fmt(update.version_buf), + request.resolution.value.npm.version.fmt(request.version_buf), }) catch unreachable, } else null, - .uninitialized => switch (update.version.tag) { + .uninitialized => switch (request.version.tag) { .uninitialized => try allocator.dupe(u8, latest), else => null, }, else => null, - } orelse try allocator.dupe(u8, update.version.literal.slice(update.version_buf)); + } orelse try allocator.dupe(u8, request.version.literal.slice(request.version_buf)); } } } @@ -5079,6 +5080,7 @@ pub const PackageManager = struct { // Corresponds to possible commands from the CLI. pub const Subcommand = enum { install, + update, pm, add, remove, @@ -5086,17 +5088,7 @@ pub const PackageManager = struct { unlink, }; - pub fn init( - ctx: Command.Context, - comptime subcommand: Subcommand, - ) !*PackageManager { - return initMaybeInstall(ctx, subcommand); - } - - fn initMaybeInstall( - ctx: Command.Context, - comptime subcommand: Subcommand, - ) !*PackageManager { + pub fn init(ctx: Command.Context, comptime subcommand: Subcommand) !*PackageManager { const cli = try CommandLineArguments.parse(ctx.allocator, subcommand); if (comptime subcommand == .install) { @@ -5443,21 +5435,19 @@ pub const PackageManager = struct { try package_json_file.pwriteAll("{\"dependencies\": {}}", 0); } - pub inline fn add( - ctx: Command.Context, - ) !void { + pub inline fn update(ctx: Command.Context) !void { + try updatePackageJSONAndInstall(ctx, .update, .update); + } + + pub inline fn add(ctx: Command.Context) !void { try updatePackageJSONAndInstall(ctx, .add, .add); } - pub inline fn remove( - ctx: Command.Context, - ) !void { + pub inline fn remove(ctx: Command.Context) !void { try updatePackageJSONAndInstall(ctx, .remove, .remove); } - pub inline fn link( - ctx: Command.Context, - ) !void { + pub inline fn link(ctx: Command.Context) !void { var manager = PackageManager.init(ctx, .link) catch |err| brk: { if (err == error.MissingPackageJSON) { try attemptToCreatePackageJSON(); @@ -5602,14 +5592,12 @@ pub const PackageManager = struct { } else { // bun link lodash switch (manager.options.log_level) { - inline else => |log_level| try updatePackageJSONAndInstallWithManager(ctx, manager, .link, log_level), + inline else => |log_level| try manager.updatePackageJSONAndInstallWithManager(ctx, .link, log_level), } } } - pub inline fn unlink( - ctx: Command.Context, - ) !void { + pub inline fn unlink(ctx: Command.Context) !void { var manager = PackageManager.init(ctx, .unlink) catch |err| brk: { if (err == error.MissingPackageJSON) { try attemptToCreatePackageJSON(); @@ -5770,6 +5758,10 @@ pub const PackageManager = struct { clap.parseParam("<POS> ... ") catch unreachable, }; + const update_params = install_params_ ++ [_]ParamType{ + clap.parseParam("<POS> ... \"name\" of packages to update") catch unreachable, + }; + const pm_params = install_params_ ++ [_]ParamType{ clap.parseParam("<POS> ... ") catch unreachable, }; @@ -5848,6 +5840,7 @@ pub const PackageManager = struct { pub fn parse(allocator: std.mem.Allocator, comptime subcommand: Subcommand) !CommandLineArguments { comptime var params: []const ParamType = &switch (subcommand) { .install => install_params, + .update => update_params, .pm => pm_params, .add => add_params, .remove => remove_params, @@ -6087,15 +6080,22 @@ pub const PackageManager = struct { comptime op: Lockfile.Package.Diff.Op, comptime subcommand: Subcommand, ) !void { - var manager = PackageManager.init(ctx, subcommand) catch |err| brk: { + var manager = init(ctx, subcommand) catch |err| brk: { if (err == error.MissingPackageJSON) { - if (op == .remove) { - Output.prettyErrorln("<r>No package.json, so nothing to remove\n", .{}); - Global.crash(); + switch (op) { + .update => { + Output.prettyErrorln("<r>No package.json, so nothing to update\n", .{}); + Global.crash(); + }, + .remove => { + Output.prettyErrorln("<r>No package.json, so nothing to remove\n", .{}); + Global.crash(); + }, + else => { + try attemptToCreatePackageJSON(); + break :brk try PackageManager.init(ctx, subcommand); + }, } - - try attemptToCreatePackageJSON(); - break :brk try PackageManager.init(ctx, subcommand); } return err; @@ -6107,13 +6107,13 @@ pub const PackageManager = struct { } switch (manager.options.log_level) { - inline else => |log_level| try updatePackageJSONAndInstallWithManager(ctx, manager, op, log_level), + inline else => |log_level| try manager.updatePackageJSONAndInstallWithManager(ctx, op, log_level), } } fn updatePackageJSONAndInstallWithManager( - ctx: Command.Context, manager: *PackageManager, + ctx: Command.Context, comptime op: Lockfile.Package.Diff.Op, comptime log_level: Options.LogLevel, ) !void { @@ -6125,7 +6125,7 @@ pub const PackageManager = struct { const off = @as(u64, @intCast(std.time.milliTimestamp())); switch (op) { - .update, .add => { + .add => { const filler = @import("../cli.zig").HelpCommand.packages_to_add_filler; examples_to_print[0] = filler[@as(usize, @intCast((off) % filler.len))]; @@ -6210,9 +6210,8 @@ pub const PackageManager = struct { } var updates = UpdateRequest.parse(ctx.allocator, ctx.log, manager.options.positionals[1..], &update_requests, op); - try updatePackageJSONAndInstallWithManagerWithUpdates( + try manager.updatePackageJSONAndInstallWithManagerWithUpdates( ctx, - manager, updates, false, op, @@ -6221,8 +6220,8 @@ pub const PackageManager = struct { } fn updatePackageJSONAndInstallWithManagerWithUpdates( - ctx: Command.Context, manager: *PackageManager, + ctx: Command.Context, updates: []UpdateRequest, auto_free: bool, comptime op: Lockfile.Package.Diff.Op, @@ -6304,7 +6303,7 @@ pub const PackageManager = struct { .remove => { // if we're removing, they don't have to specify where it is installed in the dependencies list // they can even put it multiple times and we will just remove all of them - for (updates) |update| { + for (updates) |request| { inline for ([_]string{ "dependencies", "devDependencies", "optionalDependencies", "peerDependencies" }) |list| { if (current_package_json.asProperty(list)) |query| { if (query.expr.data == .e_object) { @@ -6313,7 +6312,7 @@ pub const PackageManager = struct { var new_len = dependencies.len; while (i < dependencies.len) : (i += 1) { if (dependencies[i].key.?.data == .e_string) { - if (dependencies[i].key.?.data.e_string.eql(string, update.name)) { + if (dependencies[i].key.?.data.e_string.eql(string, request.name)) { if (new_len > 1) { dependencies[i] = dependencies[new_len - 1]; new_len -= 1; @@ -6354,7 +6353,7 @@ pub const PackageManager = struct { } manager.to_remove = updates; }, - .link, .add, .update => { + .link, .add => { try PackageJSONEditor.edit( ctx.allocator, updates, @@ -6364,6 +6363,10 @@ pub const PackageManager = struct { ); manager.package_json_updates = updates; }, + .update => { + manager.package_json_updates = updates; + manager.to_update = true; + }, else => {}, } @@ -6397,8 +6400,8 @@ pub const PackageManager = struct { try manager.installWithManager(ctx, new_package_json_source, log_level); if (op == .update or op == .add or op == .link) { - for (manager.package_json_updates) |update| { - if (update.failed) { + for (manager.package_json_updates) |request| { + if (request.failed) { Global.exit(1); return; } @@ -6454,14 +6457,14 @@ pub const PackageManager = struct { bun.copy(u8, &node_modules_buf, "node_modules" ++ std.fs.path.sep_str); var offset_buf = node_modules_buf["node_modules/".len..]; const name_hashes = manager.lockfile.packages.items(.name_hash); - for (updates) |update| { + for (updates) |request| { // If the package no longer exists in the updated lockfile, delete the directory // This is not thorough. // It does not handle nested dependencies // This is a quick & dirty cleanup intended for when deleting top-level dependencies - if (std.mem.indexOfScalar(PackageNameHash, name_hashes, String.Builder.stringHash(update.name)) == null) { - bun.copy(u8, offset_buf, update.name); - cwd.deleteTree(node_modules_buf[0 .. "node_modules/".len + update.name.len]) catch {}; + if (std.mem.indexOfScalar(PackageNameHash, name_hashes, String.Builder.stringHash(request.name)) == null) { + bun.copy(u8, offset_buf, request.name); + cwd.deleteTree(node_modules_buf[0 .. "node_modules/".len + request.name.len]) catch {}; } } @@ -6500,7 +6503,7 @@ pub const PackageManager = struct { var package_json_cwd: string = ""; pub inline fn install(ctx: Command.Context) !void { - var manager = initMaybeInstall(ctx, .install) catch |err| { + var manager = init(ctx, .install) catch |err| { if (err == error.SwitchToBunAdd) { return add(ctx); } @@ -7493,6 +7496,7 @@ pub const PackageManager = struct { &lockfile, &root, &maybe_root, + if (manager.to_update) manager.package_json_updates else null, mapping, ); @@ -7666,9 +7670,9 @@ pub const PackageManager = struct { } if (manager.lockfile.packages.len > 0) { - for (manager.package_json_updates) |update| { + for (manager.package_json_updates) |request| { // prevent redundant errors - if (update.failed) { + if (request.failed) { return error.InstallFailed; } } @@ -7845,8 +7849,8 @@ pub const PackageManager = struct { } } else if (manager.summary.remove > 0) { if (manager.to_remove.len > 0) { - for (manager.to_remove) |update| { - Output.prettyln(" <r><red>-<r> {s}", .{update.name}); + for (manager.to_remove) |request| { + Output.prettyln(" <r><red>-<r> {s}", .{request.name}); } } |