Skip to content

Commit

Permalink
root bins
Browse files Browse the repository at this point in the history
  • Loading branch information
dylan-conway committed Dec 15, 2024
1 parent 86aa496 commit 91b7e28
Show file tree
Hide file tree
Showing 6 changed files with 511 additions and 152 deletions.
82 changes: 82 additions & 0 deletions src/install/bin.zig
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,48 @@ pub const Bin = extern struct {
return 0;
}

pub fn eql(
l: *const Bin,
r: *const Bin,
l_buf: string,
l_extern_strings: []const ExternalString,
r_buf: string,
r_extern_strings: []const ExternalString,
) bool {
if (l.tag != r.tag) return false;

return switch (l.tag) {
.none => true,
.file => l.value.file.eql(r.value.file, l_buf, r_buf),
.dir => l.value.dir.eql(r.value.dir, l_buf, r_buf),
.named_file => l.value.named_file[0].eql(r.value.named_file[0], l_buf, r_buf) and
l.value.named_file[1].eql(r.value.named_file[1], l_buf, r_buf),
.map => {
const l_list = l.value.map.get(l_extern_strings);
const r_list = r.value.map.get(r_extern_strings);
if (l_list.len != r_list.len) return false;

// assuming these maps are small without duplicate keys
outer: for (0..l_list.len / 2) |i| {
for (0..r_list.len / 2) |j| {
if (l_list[i].hash == r_list[j].hash) {
if (l_list[i + 1].hash != r_list[j + 1].hash) {
return false;
}

continue :outer;
}
}

// not found
return false;
}

return true;
},
};
}

pub fn clone(this: *const Bin, buf: []const u8, prev_external_strings: []const ExternalString, all_extern_strings: []ExternalString, extern_strings_slice: []ExternalString, comptime StringBuilder: type, builder: StringBuilder) Bin {
switch (this.tag) {
.none => {
Expand Down Expand Up @@ -225,6 +267,46 @@ pub const Bin = extern struct {
return .{};
}

/// Writes value of bin to a single line, either as a string or object. Cannot be `.none` because a value is expected to be
/// written to the json, as a property value or array value.
pub fn toSingleLineJson(this: *const Bin, buf: string, extern_strings: []const ExternalString, writer: anytype) @TypeOf(writer).Error!void {
bun.debugAssert(this.tag != .none);
switch (this.tag) {
.none => {},
.file => {
try writer.print("{}", .{this.value.file.fmtJson(buf, .{})});
},
.named_file => {
try writer.writeByte('{');
try writer.print(" {}: {} ", .{
this.value.named_file[0].fmtJson(buf, .{}),
this.value.named_file[1].fmtJson(buf, .{}),
});
try writer.writeByte('}');
},
.dir => {
try writer.print("{}", .{this.value.dir.fmtJson(buf, .{})});
},
.map => {
try writer.writeByte('{');
const list = this.value.map.get(extern_strings);
var first = true;
var i: usize = 0;
while (i < list.len) : (i += 2) {
if (!first) {
try writer.writeByte(',');
}
first = false;
try writer.print(" {}: {}", .{
list[i].value.fmtJson(buf, .{}),
list[i + 1].value.fmtJson(buf, .{}),
});
}
try writer.writeAll(" }");
},
}
}

pub fn init() Bin {
return bun.serializable(.{ .tag = .none, .value = Value.init(.{ .none = {} }) });
}
Expand Down
108 changes: 37 additions & 71 deletions src/install/bun.lock.zig
Original file line number Diff line number Diff line change
Expand Up @@ -771,16 +771,25 @@ pub const Stringifier = struct {
// folder -> [ "name@path", deps..., ... ]
// workspace -> [ "name@workspace:path", version or "", deps..., ... ]
// tarball -> [ "name@tarball", deps..., ... ]
// root -> [ "name@root:" ]
// root -> [ "name@root:", bins ]
// git -> [ "name@git+repo", deps..., ... ]
// github -> [ "name@github:user/repo", deps..., ... ]

switch (res.tag) {
.root => {
try writer.print("[\"{}@root:\"]", .{
try writer.print("[\"{}@root:\", ", .{
pkg_name.fmtJson(buf, .{ .quote = false }),
// we don't read the root package version into the binary lockfile
});

try writer.writeByte('{');
if (pkg_bin.tag != .none) {
try writer.writeAll(if (pkg_bin.tag == .dir) " \"binDir\": " else " \"bin\": ");
try pkg_bin.toSingleLineJson(buf, lockfile.buffers.extern_strings.items, writer);
try writer.writeAll(" }]");
} else {
try writer.writeAll("}]");
}
},
.folder => {
try writer.print("[\"{}@file:{}\", ", .{
Expand Down Expand Up @@ -989,75 +998,14 @@ pub const Stringifier = struct {
try Negatable(Npm.Architecture).toJson(meta.arch, writer);
}

switch (bin.tag) {
.none => {},
.file => {
if (any) {
try writer.writeByte(',');
} else {
any = true;
}
try writer.print(
\\ "bin": {}
, .{
bin.value.file.fmtJson(buf, .{}),
});
},
.named_file => {
if (any) {
try writer.writeByte(',');
} else {
any = true;
}
try writer.writeAll(
\\ "bin": {
);
try writer.print(
\\ {}: {}
, .{
bin.value.named_file[0].fmtJson(buf, .{}),
bin.value.named_file[1].fmtJson(buf, .{}),
});
try writer.writeByte('}');
},
.dir => {
if (any) {
try writer.writeByte(',');
} else {
any = true;
}
try writer.print(
\\ "binDir": {}
, .{
bin.value.dir.fmtJson(buf, .{}),
});
},
.map => {
if (any) {
try writer.writeByte(',');
} else {
any = true;
}
try writer.writeAll(
\\ "bin": {
);
const list = bin.value.map.get(extern_strings);
var first = true;
var i: usize = 0;
while (i < list.len) : (i += 2) {
if (!first) {
try writer.writeAll(",");
}
first = false;
try writer.print(
\\ {}: {}
, .{
list[i].value.fmtJson(buf, .{}),
list[i + 1].value.fmtJson(buf, .{}),
});
}
try writer.writeByte('}');
},
if (bin.tag != .none) {
if (any) {
try writer.writeByte(',');
} else {
any = true;
}
try writer.writeAll(if (bin.tag == .dir) " \"binDir\": " else " \"bin\": ");
try bin.toSingleLineJson(buf, extern_strings, writer);
}

if (any) {
Expand Down Expand Up @@ -1623,6 +1571,24 @@ pub fn parseIntoBinaryLockfile(
// }
}
},
.root => {
if (i >= pkg_info.len) {
try log.addError(source, value.loc, "Missing package binaries object");
return error.InvalidPackageInfo;
}
const bin_obj = pkg_info.at(i);
i += 1;
if (!bin_obj.isObject()) {
try log.addError(source, bin_obj.loc, "Expected an object");
return error.InvalidPackageInfo;
}

if (bin_obj.get("bin")) |bin| {
pkg.bin = try Bin.parseAppend(allocator, bin, &string_buf, &lockfile.buffers.extern_strings);
} else if (bin_obj.get("binDir")) |bin_dir| {
pkg.bin = try Bin.parseAppendFromDirectories(allocator, bin_dir, &string_buf);
}
},
else => {},
}

Expand Down
87 changes: 17 additions & 70 deletions src/install/install.zig
Original file line number Diff line number Diff line change
Expand Up @@ -13330,70 +13330,6 @@ pub const PackageManager = struct {
}
}

// fn getPackageBin(
// this: *PackageInstaller,
// installer: *PackageInstall,
// pkg_name: string,
// pkg_name_hash: PackageNameHash,
// resolution: *const Resolution,
// ) OOM!Bin {
// defer this.fixCachedLockfilePackageSlices();

// if (resolution.tag == .npm) {
// var expired = false;
// if (this.manager.manifests.byNameHashAllowExpired(
// this.manager,
// this.manager.scopeForPackageName(pkg_name),
// pkg_name_hash,
// &expired,
// // Do not fallback to disk. These files are much larger than the package.json
// .load_from_memory,
// )) |manifest| {
// if (manifest.findByVersion(resolution.value.npm.version)) |find| {
// return find.package.bin.cloneAppend(manifest.string_buf, manifest.extern_strings_bin_entries, this.lockfile);
// }
// }
// }

// // get it from package.json
// var body_pool = Npm.Registry.BodyPool.get(this.lockfile.allocator);
// var mutable = body_pool.data;
// defer {
// body_pool.data = mutable;
// Npm.Registry.BodyPool.release(body_pool);
// }

// const source = installer.getInstalledPackageJsonSource(this.root_node_modules_folder, &mutable, resolution.tag) orelse return .{};

// initializeStore();

// var log = logger.Log.init(this.lockfile.allocator);
// defer log.deinit();

// var bin_finder = JSON.PackageJSONVersionChecker.init(
// this.lockfile.allocator,
// &source,
// &log,
// .only_bin,
// ) catch return .{};
// _ = bin_finder.parseExpr(false, false) catch return .{};

// if (bin_finder.has_found_bin) {
// var string_buf = this.lockfile.stringBuf();
// defer {
// string_buf.apply(this.lockfile);
// this.fixCachedLockfilePackageSlices();
// }

// return switch (bin_finder.found_bin) {
// .bin => |bin| try Bin.parseAppend(this.lockfile.allocator, bin, &string_buf, &this.lockfile.buffers.extern_strings),
// .dir => |dir| try Bin.parseAppendFromDirectories(this.lockfile.allocator, dir, &string_buf),
// };
// }

// return .{};
// }

// returns true if scripts are enqueued
fn enqueueLifecycleScripts(
this: *PackageInstaller,
Expand Down Expand Up @@ -14756,7 +14692,7 @@ pub const PackageManager = struct {

if (manager.options.enable.frozen_lockfile and load_result != .not_found) frozen_lockfile: {
if (load_result.loadedFromTextLockfile()) {
if (manager.lockfile.eql(lockfile_before_clean, manager.allocator) catch bun.outOfMemory()) {
if (manager.lockfile.eql(lockfile_before_clean, packages_len_before_install, manager.allocator) catch bun.outOfMemory()) {
break :frozen_lockfile;
}
} else {
Expand All @@ -14772,6 +14708,8 @@ pub const PackageManager = struct {
Global.crash();
}

const lockfile_before_install = manager.lockfile;

var install_summary = PackageInstall.Summary{
.lockfile_used_for_install = manager.lockfile,
};
Expand All @@ -14790,10 +14728,13 @@ pub const PackageManager = struct {
const did_meta_hash_change =
// If the lockfile was frozen, we already checked it
!manager.options.enable.frozen_lockfile and
if (load_result.loadedFromTextLockfile())
!try manager.lockfile.eql(lockfile_before_clean, packages_len_before_install, manager.allocator)
else
try manager.lockfile.hasMetaHashChanged(
PackageManager.verbose_install or manager.options.do.print_meta_hash_string,
@min(packages_len_before_install, manager.lockfile.packages.len),
);
PackageManager.verbose_install or manager.options.do.print_meta_hash_string,
@min(packages_len_before_install, manager.lockfile.packages.len),
);

const should_save_lockfile = did_meta_hash_change or
had_any_diffs or
Expand Down Expand Up @@ -14859,8 +14800,14 @@ pub const PackageManager = struct {
manager.lockfile.saveToDisk(save_format, manager.options.log_level.isVerbose());

if (comptime Environment.allow_assert) {
if (manager.lockfile.hasMetaHashChanged(false, packages_len_before_install) catch false) {
Output.panic("Lockfile metahash non-deterministic after saving", .{});
if (load_result.loadedFromTextLockfile()) {
if (!try manager.lockfile.eql(lockfile_before_install, packages_len_before_install, manager.allocator)) {
Output.panic("Lockfile non-deterministic after saving", .{});
}
} else {
if (manager.lockfile.hasMetaHashChanged(false, packages_len_before_install) catch false) {
Output.panic("Lockfile metahash non-deterministic after saving", .{});
}
}
}

Expand Down
Loading

0 comments on commit 91b7e28

Please sign in to comment.