aboutsummaryrefslogtreecommitdiff
path: root/src/install/install.zig
diff options
context:
space:
mode:
authorGravatar dave caruso <me@paperdave.net> 2023-10-11 02:27:07 -0700
committerGravatar GitHub <noreply@github.com> 2023-10-11 02:27:07 -0700
commit1bf28e0d77a8b2261befbdb708cefd03e0126960 (patch)
tree1d1120922f2fd935be47ab4255ac57455a0bede8 /src/install/install.zig
parent6a17ebe6696ebdf5c20de9de3281d308959c13b5 (diff)
downloadbun-1bf28e0d77a8b2261befbdb708cefd03e0126960.tar.gz
bun-1bf28e0d77a8b2261befbdb708cefd03e0126960.tar.zst
bun-1bf28e0d77a8b2261befbdb708cefd03e0126960.zip
feat(install): automatically migrate package-lock.json to bun.lockb (#6352)bun-v1.0.5
* work so far * stuff * a * basics work * stuff * yoo * build lockfile * correct * f * a * install fixture havent tested * i made it worse * lol * be more reasonable * make the test easier to pass because bun install doesn't handle obscure lockfile edge cases :/ * a * works now * ok * a * a * cool * nah * fix stuff * l * a * idfk * LAME * prettier errors * does this fix tests? * Add more safety checks to Integrity * Add another check * More careful lifetime handling * Fix linux debugger issue * a * tmp dir and snapshot test --------- Co-authored-by: Jarred SUmner <jarred@jarredsumner.com>
Diffstat (limited to 'src/install/install.zig')
-rw-r--r--src/install/install.zig231
1 files changed, 129 insertions, 102 deletions
diff --git a/src/install/install.zig b/src/install/install.zig
index 218dace5c..378401b8a 100644
--- a/src/install/install.zig
+++ b/src/install/install.zig
@@ -123,8 +123,8 @@ pub fn ExternalSlice(comptime Type: type) type {
pub fn ExternalSliceAligned(comptime Type: type, comptime alignment_: ?u29) type {
return extern struct {
- const alignment = alignment_ orelse @alignOf(*Type);
- const Slice = @This();
+ pub const alignment = alignment_ orelse @alignOf(*Type);
+ pub const Slice = @This();
pub const Child: type = Type;
@@ -170,7 +170,7 @@ pub const ExternalStringMap = extern struct {
value: ExternalStringList = .{},
};
-pub const PackageNameHash = u64;
+pub const PackageNameHash = u64; // Use String.Builder.stringHash to compute this
pub const Aligner = struct {
pub fn write(comptime Type: type, comptime Writer: type, writer: Writer, pos: usize) !usize {
@@ -2618,7 +2618,7 @@ pub const PackageManager = struct {
if (comptime Environment.allow_assert) {
std.debug.assert(dependency_id < buffers.resolutions.items.len);
std.debug.assert(package_id < this.lockfile.packages.len);
- std.debug.assert(buffers.resolutions.items[dependency_id] == invalid_package_id);
+ // std.debug.assert(buffers.resolutions.items[dependency_id] == invalid_package_id);
}
buffers.resolutions.items[dependency_id] = package_id;
const string_buf = buffers.string_bytes.items;
@@ -4430,6 +4430,9 @@ pub const PackageManager = struct {
manager.setPreinstallState(package_id, manager.lockfile, .done);
if (comptime @TypeOf(callbacks.onExtract) != void) {
+ if (ExtractCompletionContext == *PackageInstaller) {
+ extract_ctx.fixCachedLockfilePackageSlices();
+ }
callbacks.onExtract(extract_ctx, dependency_id, task.data.extract, comptime log_level);
}
@@ -6844,6 +6847,7 @@ pub const PackageManager = struct {
folder_path_buf: [bun.MAX_PATH_BYTES]u8 = undefined,
install_count: usize = 0,
successfully_installed: Bitset,
+ tree_iterator: *Lockfile.Tree.Iterator,
// For linking native binaries, we only want to link after we've installed the companion dependencies
// We don't want to introduce dependent callbacks like that for every single package
@@ -6855,6 +6859,16 @@ pub const PackageManager = struct {
node_modules_folder: std.fs.IterableDir,
};
+ /// Call when you mutate the length of `lockfile.packages`
+ pub fn fixCachedLockfilePackageSlices(this: *PackageInstaller) void {
+ var packages = this.lockfile.packages.slice();
+ this.metas = packages.items(.meta);
+ this.names = packages.items(.name);
+ this.bins = packages.items(.bin);
+ this.resolutions = packages.items(.resolution);
+ this.tree_iterator.reload(this.lockfile);
+ }
+
/// Install versions of a package which are waiting on a network request
pub fn installEnqueuedPackages(
this: *PackageInstaller,
@@ -7463,38 +7477,38 @@ pub const PackageManager = struct {
var summary = PackageInstall.Summary{};
{
- var parts = lockfile.packages.slice();
- var metas = parts.items(.meta);
- var names = parts.items(.name);
- var dependencies = lockfile.buffers.dependencies.items;
- const resolutions_buffer: []const PackageID = lockfile.buffers.resolutions.items;
- const resolution_lists: []const Lockfile.PackageIDSlice = parts.items(.resolutions);
- var resolutions = parts.items(.resolution);
-
var iterator = Lockfile.Tree.Iterator.init(lockfile);
- var installer = PackageInstaller{
- .manager = this,
- .options = &this.options,
- .metas = metas,
- .bins = parts.items(.bin),
- .root_node_modules_folder = node_modules_folder,
- .names = names,
- .resolutions = resolutions,
- .lockfile = lockfile,
- .node = &install_node,
- .node_modules_folder = node_modules_folder,
- .progress = progress,
- .skip_verify_installed_version_number = skip_verify_installed_version_number,
- .skip_delete = skip_delete,
- .summary = &summary,
- .global_bin_dir = this.options.global_bin_dir,
- .force_install = force_install,
- .install_count = lockfile.buffers.hoisted_dependencies.items.len,
- .successfully_installed = try Bitset.initEmpty(
- this.allocator,
- lockfile.packages.len,
- ),
+ var installer: PackageInstaller = brk: {
+ // These slices potentially get resized during iteration
+ // so we want to make sure they're not accessible to the rest of this function
+ // to make mistakes harder
+ var parts = lockfile.packages.slice();
+
+ break :brk PackageInstaller{
+ .manager = this,
+ .options = &this.options,
+ .metas = parts.items(.meta),
+ .bins = parts.items(.bin),
+ .root_node_modules_folder = node_modules_folder,
+ .names = parts.items(.name),
+ .resolutions = parts.items(.resolution),
+ .lockfile = lockfile,
+ .node = &install_node,
+ .node_modules_folder = node_modules_folder,
+ .progress = progress,
+ .skip_verify_installed_version_number = skip_verify_installed_version_number,
+ .skip_delete = skip_delete,
+ .summary = &summary,
+ .global_bin_dir = this.options.global_bin_dir,
+ .force_install = force_install,
+ .install_count = lockfile.buffers.hoisted_dependencies.items.len,
+ .successfully_installed = try Bitset.initEmpty(
+ this.allocator,
+ lockfile.packages.len,
+ ),
+ .tree_iterator = &iterator,
+ };
};
while (iterator.nextNodeModulesFolder()) |node_modules| {
@@ -7587,87 +7601,95 @@ pub const PackageManager = struct {
if (!installer.options.do.install_packages) return error.InstallFailed;
summary.successfully_installed = installer.successfully_installed;
- outer: for (installer.platform_binlinks.items) |deferred| {
- const dependency_id = deferred.dependency_id;
- const package_id = resolutions_buffer[dependency_id];
- const folder = deferred.node_modules_folder;
-
- const package_resolutions: []const PackageID = resolution_lists[package_id].get(resolutions_buffer);
- const original_bin: Bin = installer.bins[package_id];
-
- for (package_resolutions) |resolved_id| {
- if (resolved_id >= names.len) continue;
- const meta: Lockfile.Package.Meta = metas[resolved_id];
-
- // This is specifically for platform-specific binaries
- if (meta.os == .all and meta.arch == .all) continue;
-
- // Don't attempt to link incompatible binaries
- if (meta.isDisabled()) continue;
-
- const name = lockfile.str(&dependencies[dependency_id].name);
-
- if (!installer.has_created_bin) {
- if (!this.options.global) {
- if (comptime Environment.isWindows) {
- std.os.mkdiratW(node_modules_folder.dir.fd, bun.strings.w(".bin"), 0) catch {};
- } else {
- node_modules_folder.dir.makeDirZ(".bin") catch {};
+ {
+ var parts = lockfile.packages.slice();
+ var metas = parts.items(.meta);
+ var names = parts.items(.name);
+ var dependencies = lockfile.buffers.dependencies.items;
+ const resolutions_buffer: []const PackageID = lockfile.buffers.resolutions.items;
+ const resolution_lists: []const Lockfile.PackageIDSlice = parts.items(.resolutions);
+ outer: for (installer.platform_binlinks.items) |deferred| {
+ const dependency_id = deferred.dependency_id;
+ const package_id = resolutions_buffer[dependency_id];
+ const folder = deferred.node_modules_folder;
+
+ const package_resolutions: []const PackageID = resolution_lists[package_id].get(resolutions_buffer);
+ const original_bin: Bin = installer.bins[package_id];
+
+ for (package_resolutions) |resolved_id| {
+ if (resolved_id >= names.len) continue;
+ const meta: Lockfile.Package.Meta = metas[resolved_id];
+
+ // This is specifically for platform-specific binaries
+ if (meta.os == .all and meta.arch == .all) continue;
+
+ // Don't attempt to link incompatible binaries
+ if (meta.isDisabled()) continue;
+
+ const name = lockfile.str(&dependencies[dependency_id].name);
+
+ if (!installer.has_created_bin) {
+ if (!this.options.global) {
+ if (comptime Environment.isWindows) {
+ std.os.mkdiratW(node_modules_folder.dir.fd, bun.strings.w(".bin"), 0) catch {};
+ } else {
+ node_modules_folder.dir.makeDirZ(".bin") catch {};
+ }
}
+ if (comptime Environment.isPosix)
+ Bin.Linker.umask = C.umask(0);
+ installer.has_created_bin = true;
}
- if (comptime Environment.isPosix)
- Bin.Linker.umask = C.umask(0);
- installer.has_created_bin = true;
- }
- var bin_linker = Bin.Linker{
- .bin = original_bin,
- .package_installed_node_modules = bun.toFD(folder.dir.fd),
- .root_node_modules_folder = bun.toFD(node_modules_folder.dir.fd),
- .global_bin_path = this.options.bin_path,
- .global_bin_dir = this.options.global_bin_dir.dir,
+ var bin_linker = Bin.Linker{
+ .bin = original_bin,
+ .package_installed_node_modules = bun.toFD(folder.dir.fd),
+ .root_node_modules_folder = bun.toFD(node_modules_folder.dir.fd),
+ .global_bin_path = this.options.bin_path,
+ .global_bin_dir = this.options.global_bin_dir.dir,
- .package_name = strings.StringOrTinyString.init(name),
- .string_buf = lockfile.buffers.string_bytes.items,
- .extern_string_buf = lockfile.buffers.extern_strings.items,
- };
+ .package_name = strings.StringOrTinyString.init(name),
+ .string_buf = lockfile.buffers.string_bytes.items,
+ .extern_string_buf = lockfile.buffers.extern_strings.items,
+ };
- bin_linker.link(this.options.global);
+ bin_linker.link(this.options.global);
- if (bin_linker.err) |err| {
- if (comptime log_level != .silent) {
- const fmt = "\n<r><red>error:<r> linking <b>{s}<r>: {s}\n";
- const args = .{ name, @errorName(err) };
+ if (bin_linker.err) |err| {
+ if (comptime log_level != .silent) {
+ const fmt = "\n<r><red>error:<r> linking <b>{s}<r>: {s}\n";
+ const args = .{ name, @errorName(err) };
- if (comptime log_level.showProgress()) {
- switch (Output.enable_ansi_colors) {
- inline else => |enable_ansi_colors| {
- this.progress.log(comptime Output.prettyFmt(fmt, enable_ansi_colors), args);
- },
+ if (comptime log_level.showProgress()) {
+ switch (Output.enable_ansi_colors) {
+ inline else => |enable_ansi_colors| {
+ this.progress.log(comptime Output.prettyFmt(fmt, enable_ansi_colors), args);
+ },
+ }
+ } else {
+ Output.prettyErrorln(fmt, args);
}
- } else {
- Output.prettyErrorln(fmt, args);
}
+
+ if (this.options.enable.fail_early) Global.crash();
}
- if (this.options.enable.fail_early) Global.crash();
+ continue :outer;
}
- continue :outer;
- }
-
- if (comptime log_level != .silent) {
- const fmt = "\n<r><yellow>warn:<r> no compatible binaries found for <b>{s}<r>\n";
- const args = .{lockfile.str(&names[package_id])};
+ if (comptime log_level != .silent) {
+ const fmt = "\n<r><yellow>warn:<r> no compatible binaries found for <b>{s}<r>\n";
+ const args = .{lockfile.str(&names[package_id])};
- if (comptime log_level.showProgress()) {
- switch (Output.enable_ansi_colors) {
- inline else => |enable_ansi_colors| {
- this.progress.log(comptime Output.prettyFmt(fmt, enable_ansi_colors), args);
- },
+ if (comptime log_level.showProgress()) {
+ switch (Output.enable_ansi_colors) {
+ inline else => |enable_ansi_colors| {
+ this.progress.log(comptime Output.prettyFmt(fmt, enable_ansi_colors), args);
+ },
+ }
+ } else {
+ Output.prettyErrorln(fmt, args);
}
- } else {
- Output.prettyErrorln(fmt, args);
}
}
}
@@ -7726,15 +7748,17 @@ pub const PackageManager = struct {
)
else
.{ .not_found = {} };
+
var root = Lockfile.Package{};
- var needs_new_lockfile = load_lockfile_result != .ok or (load_lockfile_result.ok.buffers.dependencies.items.len == 0 and manager.package_json_updates.len > 0);
+ var needs_new_lockfile = load_lockfile_result != .ok or
+ (load_lockfile_result.ok.buffers.dependencies.items.len == 0 and manager.package_json_updates.len > 0);
+
// this defaults to false
// but we force allowing updates to the lockfile when you do bun add
var had_any_diffs = false;
manager.progress = .{};
// Step 2. Parse the package.json file
- //
var package_json_source = logger.Source.initPathString(package_json_cwd, package_json_contents);
switch (load_lockfile_result) {
@@ -7750,6 +7774,9 @@ pub const PackageManager = struct {
.read_file => Output.prettyError("<r><red>error<r> reading lockfile:<r> {s}\n<r>", .{
@errorName(cause.value),
}),
+ .migrating => Output.prettyError("<r><red>error<r> migrating lockfile:<r> {s}\n<r>", .{
+ @errorName(cause.value),
+ }),
}
if (manager.options.enable.fail_early) {