mirror of
https://github.com/oven-sh/bun
synced 2026-02-17 06:12:08 +00:00
Compare commits
1 Commits
claude/gra
...
claude/yar
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2cf9f7595b |
@@ -87,6 +87,7 @@ pub const Features = struct {
|
||||
pub var unsupported_uv_function: usize = 0;
|
||||
pub var exited: usize = 0;
|
||||
pub var yarn_migration: usize = 0;
|
||||
pub var yarn_berry_migration: usize = 0;
|
||||
pub var pnpm_migration: usize = 0;
|
||||
pub var yaml_parse: usize = 0;
|
||||
pub var cpu_profile: usize = 0;
|
||||
|
||||
@@ -114,7 +114,7 @@ pub const LoadResult = union(enum) {
|
||||
ok: struct {
|
||||
lockfile: *Lockfile,
|
||||
loaded_from_binary_lockfile: bool,
|
||||
migrated: enum { none, npm, yarn, pnpm } = .none,
|
||||
migrated: enum { none, npm, yarn, yarn_berry, pnpm } = .none,
|
||||
serializer_result: Serializer.SerializerLoadResult,
|
||||
format: LockfileFormat,
|
||||
},
|
||||
@@ -208,6 +208,7 @@ pub const LoadResult = union(enum) {
|
||||
.pnpm => .{ .v1, true },
|
||||
.npm => .{ .v0, true },
|
||||
.yarn => .{ .v0, true },
|
||||
.yarn_berry => .{ .v0, true },
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -977,7 +978,16 @@ const PendingResolution = struct {
|
||||
|
||||
const PendingResolutions = std.array_list.Managed(PendingResolution);
|
||||
|
||||
pub fn fetchNecessaryPackageMetadataAfterYarnOrPnpmMigration(this: *Lockfile, manager: *PackageManager, comptime update_os_cpu: bool) OOM!void {
|
||||
pub const MigrationType = enum {
|
||||
// pnpm needs to get dependencies from npm registry (it stores them under resolved without semver)
|
||||
pnpm,
|
||||
// yarn classic also needs to get os/cpu data from npm registry
|
||||
yarn_classic,
|
||||
// yarn berry only needs to get integrity data from npm registry
|
||||
yarn_berry,
|
||||
};
|
||||
|
||||
pub fn fetchNecessaryPackageMetadataAfterYarnOrPnpmMigration(this: *Lockfile, manager: *PackageManager, comptime migration_type: MigrationType) OOM!void {
|
||||
manager.populateManifestCache(.all) catch return;
|
||||
|
||||
const pkgs = this.packages.slice();
|
||||
@@ -986,28 +996,28 @@ pub fn fetchNecessaryPackageMetadataAfterYarnOrPnpmMigration(this: *Lockfile, ma
|
||||
const pkg_name_hashes = pkgs.items(.name_hash);
|
||||
const pkg_resolutions = pkgs.items(.resolution);
|
||||
const pkg_bins = pkgs.items(.bin);
|
||||
const pkg_metas = if (update_os_cpu) pkgs.items(.meta) else undefined;
|
||||
const pkg_metas = pkgs.items(.meta);
|
||||
|
||||
if (update_os_cpu) {
|
||||
for (pkg_names, pkg_name_hashes, pkg_resolutions, pkg_bins, pkg_metas) |pkg_name, pkg_name_hash, pkg_res, *pkg_bin, *pkg_meta| {
|
||||
switch (pkg_res.tag) {
|
||||
.npm => {
|
||||
const manifest = manager.manifests.byNameHash(
|
||||
manager,
|
||||
manager.scopeForPackageName(pkg_name.slice(this.buffers.string_bytes.items)),
|
||||
pkg_name_hash,
|
||||
.load_from_memory_fallback_to_disk,
|
||||
false,
|
||||
) orelse {
|
||||
continue;
|
||||
};
|
||||
for (pkg_names, pkg_name_hashes, pkg_resolutions, pkg_bins, pkg_metas) |pkg_name, pkg_name_hash, pkg_res, *pkg_bin, *pkg_meta| {
|
||||
switch (pkg_res.tag) {
|
||||
.npm => {
|
||||
const manifest = manager.manifests.byNameHash(
|
||||
manager,
|
||||
manager.scopeForPackageName(pkg_name.slice(this.buffers.string_bytes.items)),
|
||||
pkg_name_hash,
|
||||
.load_from_memory_fallback_to_disk,
|
||||
false,
|
||||
) orelse continue;
|
||||
|
||||
const pkg = manifest.findByVersion(pkg_res.value.npm.version) orelse {
|
||||
continue;
|
||||
};
|
||||
const pkg = manifest.findByVersion(pkg_res.value.npm.version) orelse continue;
|
||||
|
||||
var builder = manager.lockfile.stringBuilder();
|
||||
var builder = manager.lockfile.stringBuilder();
|
||||
|
||||
if (migration_type == .yarn_berry) {
|
||||
if (pkg_meta.integrity.tag == .unknown) {
|
||||
pkg_meta.integrity = pkg.package.integrity;
|
||||
}
|
||||
} else {
|
||||
var bin_extern_strings_count: u32 = 0;
|
||||
|
||||
bin_extern_strings_count += pkg.package.bin.count(manifest.string_buf, manifest.extern_strings_bin_entries, @TypeOf(&builder), &builder);
|
||||
@@ -1022,53 +1032,17 @@ pub fn fetchNecessaryPackageMetadataAfterYarnOrPnpmMigration(this: *Lockfile, ma
|
||||
|
||||
pkg_bin.* = pkg.package.bin.clone(manifest.string_buf, manifest.extern_strings_bin_entries, extern_strings_list.items, extern_strings, @TypeOf(&builder), &builder);
|
||||
|
||||
// Update os/cpu metadata if not already set
|
||||
if (pkg_meta.os == .all) {
|
||||
pkg_meta.os = pkg.package.os;
|
||||
if (migration_type == .yarn_classic) {
|
||||
if (pkg_meta.os == .all) {
|
||||
pkg_meta.os = pkg.package.os;
|
||||
}
|
||||
if (pkg_meta.arch == .all) {
|
||||
pkg_meta.arch = pkg.package.cpu;
|
||||
}
|
||||
}
|
||||
if (pkg_meta.arch == .all) {
|
||||
pkg_meta.arch = pkg.package.cpu;
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (pkg_names, pkg_name_hashes, pkg_resolutions, pkg_bins) |pkg_name, pkg_name_hash, pkg_res, *pkg_bin| {
|
||||
switch (pkg_res.tag) {
|
||||
.npm => {
|
||||
const manifest = manager.manifests.byNameHash(
|
||||
manager,
|
||||
manager.scopeForPackageName(pkg_name.slice(this.buffers.string_bytes.items)),
|
||||
pkg_name_hash,
|
||||
.load_from_memory_fallback_to_disk,
|
||||
false,
|
||||
) orelse {
|
||||
continue;
|
||||
};
|
||||
|
||||
const pkg = manifest.findByVersion(pkg_res.value.npm.version) orelse {
|
||||
continue;
|
||||
};
|
||||
|
||||
var builder = manager.lockfile.stringBuilder();
|
||||
|
||||
var bin_extern_strings_count: u32 = 0;
|
||||
|
||||
bin_extern_strings_count += pkg.package.bin.count(manifest.string_buf, manifest.extern_strings_bin_entries, @TypeOf(&builder), &builder);
|
||||
|
||||
try builder.allocate();
|
||||
defer builder.clamp();
|
||||
|
||||
var extern_strings_list = &manager.lockfile.buffers.extern_strings;
|
||||
try extern_strings_list.ensureUnusedCapacity(manager.lockfile.allocator, bin_extern_strings_count);
|
||||
extern_strings_list.items.len += bin_extern_strings_count;
|
||||
const extern_strings = extern_strings_list.items[extern_strings_list.items.len - bin_extern_strings_count ..];
|
||||
|
||||
pkg_bin.* = pkg.package.bin.clone(manifest.string_buf, manifest.extern_strings_bin_entries, extern_strings_list.items, extern_strings, @TypeOf(&builder), &builder);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -824,7 +824,7 @@ pub fn migratePnpmLockfile(
|
||||
|
||||
try lockfile.resolve(log);
|
||||
|
||||
try lockfile.fetchNecessaryPackageMetadataAfterYarnOrPnpmMigration(manager, false);
|
||||
try lockfile.fetchNecessaryPackageMetadataAfterYarnOrPnpmMigration(manager, .pnpm);
|
||||
|
||||
try updatePackageJsonAfterMigration(allocator, manager, log, dir, found_patches);
|
||||
|
||||
|
||||
@@ -100,6 +100,372 @@ pub fn ResolutionType(comptime SemverIntType: type) type {
|
||||
};
|
||||
}
|
||||
|
||||
const FromYarnBerryLockfileError = OOM || error{InvalidYarnBerryLockfile};
|
||||
|
||||
/// Parse Yarn Berry resolution: "package@protocol:details" or "package@protocol:details::metadata"
|
||||
pub fn fromYarnBerryLockfile(res_str: []const u8, string_buf: *String.Buf) FromYarnBerryLockfileError!Resolution {
|
||||
const at_idx = strings.lastIndexOfChar(res_str, '@') orelse return error.InvalidYarnBerryLockfile;
|
||||
var protocol_part = res_str[at_idx + 1 ..];
|
||||
|
||||
// Extract __archiveUrl from ::metadata if present (custom registry URLs)
|
||||
var archive_url: ?[]const u8 = null;
|
||||
if (strings.indexOf(protocol_part, "::__archiveUrl=")) |archive_idx| {
|
||||
const encoded_url = protocol_part[archive_idx + "::__archiveUrl=".len ..];
|
||||
protocol_part = protocol_part[0..archive_idx];
|
||||
archive_url = encoded_url;
|
||||
} else if (strings.indexOf(protocol_part, "::")) |idx| {
|
||||
protocol_part = protocol_part[0..idx];
|
||||
}
|
||||
|
||||
// npm:version
|
||||
if (strings.withoutPrefixIfPossibleComptime(protocol_part, "npm:")) |version_str| {
|
||||
const version_literal = try string_buf.append(version_str);
|
||||
const parsed = Semver.Version.parse(version_literal.sliced(string_buf.bytes.items));
|
||||
if (!parsed.valid or parsed.version.major == null or parsed.version.minor == null or parsed.version.patch == null) {
|
||||
return error.InvalidYarnBerryLockfile;
|
||||
}
|
||||
|
||||
// Use custom registry URL if present
|
||||
var url: String = .{};
|
||||
if (archive_url) |encoded| {
|
||||
var decoded_buf: [2048]u8 = undefined;
|
||||
var decoded_stream = std.io.fixedBufferStream(&decoded_buf);
|
||||
const decoded_len = PercentEncoding.decode(@TypeOf(decoded_stream).Writer, decoded_stream.writer(), encoded) catch 0;
|
||||
if (decoded_len > 0) {
|
||||
url = try string_buf.append(decoded_buf[0..decoded_len]);
|
||||
}
|
||||
}
|
||||
|
||||
return This.init(.{ .npm = .{ .version = parsed.version.min(), .url = url } });
|
||||
}
|
||||
|
||||
// link:path -> symlink
|
||||
if (strings.withoutPrefixIfPossibleComptime(protocol_part, "link:")) |path| {
|
||||
return This.init(.{ .symlink = try string_buf.append(path) });
|
||||
}
|
||||
|
||||
// file:path -> folder
|
||||
if (strings.withoutPrefixIfPossibleComptime(protocol_part, "file:")) |path| {
|
||||
return This.init(.{ .folder = try string_buf.append(path) });
|
||||
}
|
||||
|
||||
// portal:path -> folder
|
||||
if (strings.withoutPrefixIfPossibleComptime(protocol_part, "portal:")) |path| {
|
||||
return This.init(.{ .folder = try string_buf.append(path) });
|
||||
}
|
||||
|
||||
// github:owner/repo#ref
|
||||
if (strings.withoutPrefixIfPossibleComptime(protocol_part, "github:")) |github_spec| {
|
||||
return This.init(.{ .github = try Repository.parseAppendGithub(github_spec, string_buf) });
|
||||
}
|
||||
|
||||
// git:url or git+protocol:url
|
||||
if (strings.hasPrefixComptime(protocol_part, "git:") or strings.hasPrefixComptime(protocol_part, "git+")) {
|
||||
return This.init(.{ .git = try Repository.parseAppendGit(protocol_part, string_buf) });
|
||||
}
|
||||
|
||||
// https://.../*.git#... -> git resolution (github, gitlab, bitbucket, etc.)
|
||||
if (strings.hasPrefixComptime(protocol_part, "https:") or strings.hasPrefixComptime(protocol_part, "http:")) {
|
||||
if (strings.indexOf(protocol_part, ".git")) |git_idx| {
|
||||
const after_git = protocol_part[git_idx + ".git".len ..];
|
||||
const committish = strings.withoutPrefixIfPossibleComptime(after_git, "#commit=") orelse
|
||||
strings.withoutPrefixIfPossibleComptime(after_git, "#") orelse "";
|
||||
if (committish.len > 0) {
|
||||
const repo_url = protocol_part[0 .. git_idx + ".git".len];
|
||||
// GitHub: convert to github:owner/repo#commit format
|
||||
if (strings.withoutPrefixIfPossibleComptime(repo_url, "https://github.com/")) |path| {
|
||||
if (strings.indexOfChar(path, '/')) |slash_idx| {
|
||||
const owner = path[0..slash_idx];
|
||||
const repo = path[slash_idx + 1 .. path.len - ".git".len];
|
||||
const short_commit = shortCommit(committish);
|
||||
var resolved_buf: [256]u8 = undefined;
|
||||
const resolved_str = std.fmt.bufPrint(&resolved_buf, "{s}-{s}-{s}", .{ owner, repo, short_commit }) catch "";
|
||||
return This.init(.{ .github = .{
|
||||
.owner = try string_buf.append(owner),
|
||||
.repo = try string_buf.append(repo),
|
||||
.committish = try string_buf.append(committish),
|
||||
.resolved = if (resolved_str.len > 0) try string_buf.append(resolved_str) else .{},
|
||||
} });
|
||||
}
|
||||
}
|
||||
// Non-GitHub (gitlab, bitbucket, etc.): git+url#commit format
|
||||
return This.init(.{ .git = .{
|
||||
.repo = try string_buf.append(repo_url),
|
||||
.committish = try string_buf.append(committish),
|
||||
.resolved = try string_buf.append(committish),
|
||||
} });
|
||||
}
|
||||
}
|
||||
return This.init(.{ .remote_tarball = try string_buf.append(protocol_part) });
|
||||
}
|
||||
|
||||
// Fallback: bare version without protocol (Yarn 2.x lockfiles v4/v5)
|
||||
// e.g. "lodash@4.17.21" instead of "lodash@npm:4.17.21"
|
||||
const version_literal = try string_buf.append(protocol_part);
|
||||
const parsed = Semver.Version.parse(version_literal.sliced(string_buf.bytes.items));
|
||||
if (parsed.valid and parsed.version.major != null and parsed.version.minor != null and parsed.version.patch != null) {
|
||||
return This.init(.{ .npm = .{ .version = parsed.version.min(), .url = .{} } });
|
||||
}
|
||||
|
||||
return error.InvalidYarnBerryLockfile;
|
||||
}
|
||||
|
||||
fn extractPackageName(spec: []const u8) []const u8 {
|
||||
const at_idx = if (strings.hasPrefixComptime(spec, "@"))
|
||||
strings.indexOfChar(spec[1..], '@')
|
||||
else
|
||||
strings.indexOfChar(spec, '@');
|
||||
|
||||
if (at_idx) |idx| {
|
||||
if (strings.hasPrefixComptime(spec, "@")) {
|
||||
return spec[0 .. idx + 1];
|
||||
}
|
||||
return spec[0..idx];
|
||||
}
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
fn shortCommit(committish: []const u8) []const u8 {
|
||||
return if (committish.len > 7) committish[0..7] else committish;
|
||||
}
|
||||
|
||||
fn appendShortCommit(committish: []const u8, buf: *String.Buf) !String {
|
||||
return try buf.append(shortCommit(committish));
|
||||
}
|
||||
|
||||
fn isDefaultRegistry(url: []const u8) bool {
|
||||
return strings.containsComptime(url, "registry.yarnpkg.com") or
|
||||
strings.containsComptime(url, "registry.npmjs.org");
|
||||
}
|
||||
|
||||
pub fn fromYarnV1Spec(
|
||||
first_spec: []const u8,
|
||||
resolved: []const u8,
|
||||
version: []const u8,
|
||||
string_buf: *String.Buf,
|
||||
) FromYarnBerryLockfileError!struct { Resolution, String, u64 } {
|
||||
const is_github_spec = strings.containsComptime(first_spec, "@github:");
|
||||
const is_git_spec = strings.containsComptime(first_spec, "@git+");
|
||||
const is_tarball_url_spec = strings.containsComptime(first_spec, "@http");
|
||||
|
||||
const real_name = blk: {
|
||||
if (strings.containsComptime(first_spec, "@npm:")) {
|
||||
if (strings.hasPrefixComptime(first_spec, "@")) {
|
||||
if (strings.indexOfChar(first_spec, '@')) |first_at| {
|
||||
const after_first_at = first_spec[first_at + 1 ..];
|
||||
if (strings.indexOfChar(after_first_at, '@')) |second_at_in_substr| {
|
||||
const second_at = first_at + 1 + second_at_in_substr;
|
||||
if (strings.hasPrefixComptime(first_spec[second_at..], "@npm:")) {
|
||||
const real_spec = first_spec[second_at + "@npm:".len ..];
|
||||
const real_pkg_name = extractPackageName(real_spec);
|
||||
break :blk real_pkg_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (strings.indexOfChar(first_spec, '@')) |at_pos| {
|
||||
const after_at = first_spec[at_pos + 1 ..];
|
||||
if (strings.hasPrefixComptime(after_at, "npm:")) {
|
||||
const real_spec = first_spec[at_pos + "@npm:".len ..];
|
||||
const real_pkg_name = extractPackageName(real_spec);
|
||||
break :blk real_pkg_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break :blk extractPackageName(first_spec);
|
||||
};
|
||||
|
||||
var real_name_hash = String.Builder.stringHash(real_name);
|
||||
var real_name_string = try string_buf.appendWithHash(real_name, real_name_hash);
|
||||
|
||||
var res: Resolution = undefined;
|
||||
|
||||
if (is_github_spec) {
|
||||
const at_github_idx = strings.indexOf(first_spec, "@github:") orelse {
|
||||
return error.InvalidYarnBerryLockfile;
|
||||
};
|
||||
const github_spec = first_spec[at_github_idx + "@github:".len ..];
|
||||
var repo = try Repository.parseAppendGithub(github_spec, string_buf);
|
||||
|
||||
if (repo.committish.isEmpty() and resolved.len > 0) {
|
||||
if (Resolution.fromPnpmLockfile(resolved, string_buf)) |resolved_res| {
|
||||
if (resolved_res.tag == .github) {
|
||||
repo.committish = resolved_res.value.github.committish;
|
||||
}
|
||||
} else |_| {}
|
||||
}
|
||||
|
||||
if (repo.committish.len() > 0) {
|
||||
const committish = repo.committish.slice(string_buf.bytes.items);
|
||||
repo.committish = try appendShortCommit(committish, string_buf);
|
||||
}
|
||||
|
||||
res = .init(.{ .github = repo });
|
||||
const alias_name = first_spec[0..at_github_idx];
|
||||
real_name_hash = String.Builder.stringHash(alias_name);
|
||||
real_name_string = try string_buf.appendWithHash(alias_name, real_name_hash);
|
||||
} else if (is_git_spec) {
|
||||
const at_git_idx = strings.indexOf(first_spec, "@git+") orelse {
|
||||
return error.InvalidYarnBerryLockfile;
|
||||
};
|
||||
const git_spec = first_spec[at_git_idx + 1 ..];
|
||||
|
||||
if (strings.containsComptime(git_spec, "github.com")) {
|
||||
const github_com_idx = strings.indexOf(git_spec, "github.com/") orelse {
|
||||
return error.InvalidYarnBerryLockfile;
|
||||
};
|
||||
var path = git_spec[github_com_idx + "github.com/".len ..];
|
||||
|
||||
if (strings.hasPrefixComptime(path, "git+")) {
|
||||
path = path["git+".len..];
|
||||
}
|
||||
|
||||
var hash_idx: usize = 0;
|
||||
var slash_idx: usize = 0;
|
||||
for (path, 0..) |c, i| {
|
||||
switch (c) {
|
||||
'/' => slash_idx = i,
|
||||
'#' => {
|
||||
hash_idx = i;
|
||||
break;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
const owner = path[0..slash_idx];
|
||||
var repo_part = if (hash_idx == 0) path[slash_idx + 1 ..] else path[slash_idx + 1 .. hash_idx];
|
||||
|
||||
if (strings.hasSuffixComptime(repo_part, ".git")) {
|
||||
repo_part = repo_part[0 .. repo_part.len - 4];
|
||||
}
|
||||
|
||||
var repo_result: Repository = .{
|
||||
.owner = try string_buf.append(owner),
|
||||
.repo = try string_buf.append(repo_part),
|
||||
};
|
||||
|
||||
if (hash_idx != 0) {
|
||||
const committish = path[hash_idx + 1 ..];
|
||||
repo_result.committish = try appendShortCommit(committish, string_buf);
|
||||
} else if (resolved.len > 0) {
|
||||
if (strings.indexOfChar(resolved, '#')) |resolved_hash_idx| {
|
||||
const committish = resolved[resolved_hash_idx + 1 ..];
|
||||
repo_result.committish = try appendShortCommit(committish, string_buf);
|
||||
}
|
||||
}
|
||||
|
||||
res = .init(.{ .github = repo_result });
|
||||
const alias_name = first_spec[0..at_git_idx];
|
||||
real_name_hash = String.Builder.stringHash(alias_name);
|
||||
real_name_string = try string_buf.appendWithHash(alias_name, real_name_hash);
|
||||
} else {
|
||||
const repo = try Repository.parseAppendGit(git_spec, string_buf);
|
||||
res = .init(.{ .git = repo });
|
||||
const alias_name = first_spec[0..at_git_idx];
|
||||
real_name_hash = String.Builder.stringHash(alias_name);
|
||||
real_name_string = try string_buf.appendWithHash(alias_name, real_name_hash);
|
||||
}
|
||||
} else if (is_tarball_url_spec) {
|
||||
const at_http_idx = strings.indexOf(first_spec, "@http") orelse {
|
||||
return error.InvalidYarnBerryLockfile;
|
||||
};
|
||||
const url_after_at = first_spec[at_http_idx + 1 ..];
|
||||
|
||||
if (strings.indexOf(url_after_at, "/-/")) |dash_slash_idx| {
|
||||
const before_dash_slash = url_after_at[0..dash_slash_idx];
|
||||
if (strings.lastIndexOfChar(before_dash_slash, '/')) |last_slash| {
|
||||
const real_pkg_name_from_url = before_dash_slash[last_slash + 1 ..];
|
||||
real_name_hash = String.Builder.stringHash(real_pkg_name_from_url);
|
||||
real_name_string = try string_buf.appendWithHash(real_pkg_name_from_url, real_name_hash);
|
||||
} else {
|
||||
const real_pkg_name_from_spec = first_spec[0..at_http_idx];
|
||||
real_name_hash = String.Builder.stringHash(real_pkg_name_from_spec);
|
||||
real_name_string = try string_buf.appendWithHash(real_pkg_name_from_spec, real_name_hash);
|
||||
}
|
||||
} else {
|
||||
const real_pkg_name_from_spec = first_spec[0..at_http_idx];
|
||||
real_name_hash = String.Builder.stringHash(real_pkg_name_from_spec);
|
||||
real_name_string = try string_buf.appendWithHash(real_pkg_name_from_spec, real_name_hash);
|
||||
}
|
||||
const version_str = try string_buf.append(version);
|
||||
const parsed = Semver.Version.parse(version_str.sliced(string_buf.bytes.items));
|
||||
|
||||
if (!parsed.valid or parsed.version.major == null or parsed.version.minor == null or parsed.version.patch == null) {
|
||||
return error.InvalidYarnBerryLockfile;
|
||||
}
|
||||
|
||||
res = .init(.{ .npm = .{
|
||||
.version = parsed.version.min(),
|
||||
.url = try string_buf.append(url_after_at),
|
||||
} });
|
||||
} else if (resolved.len == 0) {
|
||||
if (strings.containsComptime(first_spec, "@file:")) {
|
||||
const at_file_idx = strings.indexOf(first_spec, "@file:") orelse {
|
||||
return error.InvalidYarnBerryLockfile;
|
||||
};
|
||||
const path = first_spec[at_file_idx + "@file:".len ..];
|
||||
if (strings.hasSuffixComptime(path, ".tgz") or strings.hasSuffixComptime(path, ".tar.gz")) {
|
||||
res = .init(.{ .local_tarball = try string_buf.append(path) });
|
||||
} else {
|
||||
res = .init(.{ .folder = try string_buf.append(path) });
|
||||
}
|
||||
} else {
|
||||
return error.InvalidYarnBerryLockfile;
|
||||
}
|
||||
} else if (isDefaultRegistry(resolved) and
|
||||
(strings.hasPrefixComptime(resolved, "https://") or
|
||||
strings.hasPrefixComptime(resolved, "http://")))
|
||||
{
|
||||
const version_str = try string_buf.append(version);
|
||||
const parsed = Semver.Version.parse(version_str.sliced(string_buf.bytes.items));
|
||||
|
||||
if (!parsed.valid) {
|
||||
return error.InvalidYarnBerryLockfile;
|
||||
}
|
||||
|
||||
res = .init(.{ .npm = .{
|
||||
.version = parsed.version.min(),
|
||||
.url = .{},
|
||||
} });
|
||||
} else {
|
||||
res = Resolution.fromPnpmLockfile(resolved, string_buf) catch {
|
||||
return error.InvalidYarnBerryLockfile;
|
||||
};
|
||||
|
||||
switch (res.tag) {
|
||||
.github => {
|
||||
var repo = res.value.github;
|
||||
if (repo.committish.len() > 0) {
|
||||
const committish = repo.committish.slice(string_buf.bytes.items);
|
||||
repo.committish = try appendShortCommit(committish, string_buf);
|
||||
res = .init(.{ .github = repo });
|
||||
}
|
||||
const repo_name = repo.repo.slice(string_buf.bytes.items);
|
||||
real_name_hash = String.Builder.stringHash(repo_name);
|
||||
real_name_string = repo.repo;
|
||||
},
|
||||
.git => {
|
||||
const repo = res.value.git;
|
||||
var repo_name = repo.repo.slice(string_buf.bytes.items);
|
||||
if (strings.hasSuffixComptime(repo_name, ".git")) {
|
||||
repo_name = repo_name[0 .. repo_name.len - 4];
|
||||
}
|
||||
if (strings.lastIndexOfChar(repo_name, '/')) |slash| {
|
||||
repo_name = repo_name[slash + 1 ..];
|
||||
}
|
||||
real_name_hash = String.Builder.stringHash(repo_name);
|
||||
real_name_string = try string_buf.appendWithHash(repo_name, real_name_hash);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
return .{ res, real_name_string, real_name_hash };
|
||||
}
|
||||
|
||||
const FromPnpmLockfileError = OOM || error{InvalidPnpmLockfile};
|
||||
|
||||
pub fn fromPnpmLockfile(res_str: []const u8, string_buf: *String.Buf) FromPnpmLockfileError!Resolution {
|
||||
@@ -540,6 +906,7 @@ pub fn ResolutionType(comptime SemverIntType: type) type {
|
||||
const string = []const u8;
|
||||
|
||||
const std = @import("std");
|
||||
const PercentEncoding = @import("../url.zig").PercentEncoding;
|
||||
const Repository = @import("./repository.zig").Repository;
|
||||
const VersionedURLType = @import("./versioned_url.zig").VersionedURLType;
|
||||
|
||||
|
||||
2879
src/install/yarn.zig
2879
src/install/yarn.zig
File diff suppressed because it is too large
Load Diff
413
test/cli/install/migration/__snapshots__/yarn-berry.test.ts.snap
Normal file
413
test/cli/install/migration/__snapshots__/yarn-berry.test.ts.snap
Normal file
@@ -0,0 +1,413 @@
|
||||
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
|
||||
|
||||
exports[`Yarn Berry migration simple package with conditions (v8 format) 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "test-conditions",
|
||||
"dependencies": {
|
||||
"@esbuild/darwin-arm64": "^0.21.5",
|
||||
"fsevents": "^2.3.2",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
|
||||
|
||||
"fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Yarn Berry migration optional peer dependencies 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "test-peer-meta",
|
||||
"dependencies": {
|
||||
"react": "^18.0.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"loose-envify": ["loose-envify@1.4.0", "", { "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"], "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
|
||||
|
||||
"react": ["react@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ=="],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Yarn Berry migration optional dependencies via dependenciesMeta 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "test-deps-meta",
|
||||
"dependencies": {
|
||||
"sharp": "^0.32.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.32.6", "", { "os": "darwin", "cpu": "arm64" }, ""],
|
||||
|
||||
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.32.6", "", { "os": "linux", "cpu": "x64" }, ""],
|
||||
|
||||
"sharp": ["sharp@0.32.6", "", { "dependencies": { "@img/sharp-darwin-arm64": "0.32.6", "@img/sharp-linux-x64": "0.32.6" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.32.6", "@img/sharp-linux-x64": "0.32.6" } }, "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w=="],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Yarn Berry migration bin definitions 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "test-bins",
|
||||
"dependencies": {
|
||||
"typescript": "^5.9.2",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Yarn Berry migration workspace:* protocol 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "test-workspaces",
|
||||
"dependencies": {
|
||||
"lib-a": "workspace:*",
|
||||
},
|
||||
},
|
||||
"packages/lib-a": {
|
||||
"name": "lib-a",
|
||||
"version": "1.0.0",
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"lib-a": ["lib-a@workspace:packages/lib-a"],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Yarn Berry migration v4 format (Yarn 2.x) with bare versions 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "test-v4",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.21",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Yarn Berry migration v6 format fallback with os/cpu arrays 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "test-v6",
|
||||
"dependencies": {
|
||||
"fsevents": "^2.3.2",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Yarn Berry migration real-world monorepo with Next.js, workspace:^ deps, optional peers, and platform-specific bins 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "nextjs-monorepo",
|
||||
"devDependencies": {
|
||||
"typescript": "^5.0.0",
|
||||
},
|
||||
},
|
||||
"apps/web": {
|
||||
"name": "nextjs-app",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@ui/shared": "workspace:^",
|
||||
"next": "14.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
},
|
||||
},
|
||||
"packages/shared": {
|
||||
"name": "@ui/shared",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"react": "^18.2.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@next/env": ["@next/env@14.1.0", "", {}, "sha512-Py8zIo+02ht82brwwhTg36iogzFqGLPXlRGKQw5s+qP/kMNc4MAyDeEwBKDijk6zTIbegEgu8Qy7C1LboslQAw=="],
|
||||
|
||||
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@14.1.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-nUDn7TOGcIeyQni6lZHfzNoo9S0euXnu0jhsbMOmMJUBfgsnESdjN97kM7cBqQxZa8L/bM9om/S5/1dzCrW6wQ=="],
|
||||
|
||||
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@14.1.0", "", { "os": "linux", "cpu": "x64" }, "sha512-zJ2pnoFYB1F4vmEVlb/eSe+VH679zT1VdXlZKX+pE66grOgjmKJHKacf82g/sWE4MQ4Rk2FMBCRnX+l6/TVYzQ=="],
|
||||
|
||||
"@ui/shared": ["@ui/shared@workspace:packages/shared"],
|
||||
|
||||
"busboy": ["busboy@1.6.0", "", { "dependencies": { "streamsearch": "^1.1.0" } }, "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA=="],
|
||||
|
||||
"client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="],
|
||||
|
||||
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
||||
|
||||
"loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
|
||||
|
||||
"next": ["next@14.1.0", "", { "dependencies": { "@next/env": "14.1.0", "@next/swc-darwin-arm64": "14.1.0", "@next/swc-linux-x64-gnu": "14.1.0", "busboy": "1.6.0", "styled-jsx": "5.1.1" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-wlzrsbfeSU48YQBjZhDzOwhWhGsy+uQycR8bHAOt1LY1bn3zZEcDyHQOEoN3aWzQ8LHCAJ1nqrWCc9XF2+O45Q=="],
|
||||
|
||||
"nextjs-app": ["nextjs-app@workspace:apps/web"],
|
||||
|
||||
"react": ["react@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ=="],
|
||||
|
||||
"react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "react": "^18.2.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="],
|
||||
|
||||
"scheduler": ["scheduler@0.23.0", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw=="],
|
||||
|
||||
"streamsearch": ["streamsearch@1.1.0", "", {}, "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="],
|
||||
|
||||
"styled-jsx": ["styled-jsx@5.1.1", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": "*" } }, "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw=="],
|
||||
|
||||
"typescript": ["typescript@5.3.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw=="],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Yarn Berry migration deeply nested workspace dependencies with multiple conflicting versions 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "complex-deps-monorepo",
|
||||
},
|
||||
"packages/pkg-a": {
|
||||
"name": "pkg-a",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.20",
|
||||
"react": "^18.0.0",
|
||||
},
|
||||
},
|
||||
"packages/pkg-b": {
|
||||
"name": "pkg-b",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.21",
|
||||
"pkg-a": "workspace:^",
|
||||
"react": "^17.0.0",
|
||||
},
|
||||
},
|
||||
"packages/pkg-c": {
|
||||
"name": "pkg-c",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"pkg-a": "workspace:^",
|
||||
"pkg-b": "workspace:^",
|
||||
"react": "^18.2.0",
|
||||
},
|
||||
},
|
||||
"packages/pkg-d": {
|
||||
"name": "pkg-d",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.19",
|
||||
"pkg-c": "workspace:^",
|
||||
"react": "^16.14.0",
|
||||
},
|
||||
},
|
||||
"packages/pkg-e": {
|
||||
"name": "pkg-e",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"pkg-a": "workspace:^",
|
||||
"pkg-d": "workspace:^",
|
||||
"react": "^18.0.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
||||
|
||||
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
|
||||
|
||||
"loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
|
||||
|
||||
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
||||
|
||||
"pkg-a": ["pkg-a@workspace:packages/pkg-a"],
|
||||
|
||||
"pkg-b": ["pkg-b@workspace:packages/pkg-b"],
|
||||
|
||||
"pkg-c": ["pkg-c@workspace:packages/pkg-c"],
|
||||
|
||||
"pkg-d": ["pkg-d@workspace:packages/pkg-d"],
|
||||
|
||||
"pkg-e": ["pkg-e@workspace:packages/pkg-e"],
|
||||
|
||||
"prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
|
||||
|
||||
"react": ["react@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ=="],
|
||||
|
||||
"react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||
|
||||
"pkg-b/react": ["react@17.0.2", "", { "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" } }, "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA=="],
|
||||
|
||||
"pkg-d/react": ["react@16.14.0", "", { "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", "prop-types": "^15.6.2" } }, "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g=="],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Yarn Berry migration git and GitHub dependencies: git-deps-berry 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "git-deps-test",
|
||||
"dependencies": {
|
||||
"git-pkg": "git+https://github.com/example/repo.git#v1.0.0",
|
||||
"github-pkg": "github:user/repo#main",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"git-pkg": ["git-pkg@github:example/repo#abc123d", {}, "example-repo-abc123d"],
|
||||
|
||||
"github-pkg": ["github-pkg@github:user/repo#deadbee", { "dependencies": { "is-number": "^7.0.0" } }, "user-repo-deadbee"],
|
||||
|
||||
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Yarn Berry migration non-GitHub git dependencies (gitlab, bitbucket): gitlab-deps-berry 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "gitlab-deps-test",
|
||||
"dependencies": {
|
||||
"gitlab-pkg": "git+https://gitlab.com/nickvision/tube.git#v1.0.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"gitlab-pkg": ["gitlab-pkg@git+https://gitlab.com/nickvision/tube.git#abc123def456", {}, "abc123def456"],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Yarn Berry migration npm aliases in Berry format: npm-aliases-berry 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "npm-alias-test",
|
||||
"dependencies": {
|
||||
"my-lodash": "npm:lodash@^4.17.0",
|
||||
"old-react": "npm:react@17.0.2",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
||||
|
||||
"loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
|
||||
|
||||
"my-lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
|
||||
|
||||
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
||||
|
||||
"old-react": ["react@17.0.2", "", { "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" } }, "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA=="],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Yarn Berry migration custom registry URLs: custom-registry-berry 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "custom-registry-test",
|
||||
"dependencies": {
|
||||
"private-pkg": "^1.0.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"private-pkg": ["private-pkg@1.0.0", "https://my-private-registry.com/private-pkg/-/private-pkg-1.0.0.tgz", {}, ""],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Yarn Berry migration multiple resolutions for same package (version aliasing): multi-resolution-berry 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "multi-res-test",
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0",
|
||||
"is-odd": "^3.0.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
||||
|
||||
"is-odd": ["is-odd@3.0.1", "", { "dependencies": { "is-number": "^6.0.0" } }, "sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA=="],
|
||||
|
||||
"is-odd/is-number": ["is-number@6.0.0", "", {}, "sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg=="],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
@@ -228,9 +228,34 @@ exports[`yarn.lock migration basic yarn.lock with workspace dependencies: worksp
|
||||
"lodash": "^4.17.21",
|
||||
},
|
||||
},
|
||||
"packages/a": {
|
||||
"name": "@workspace/a",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@workspace/b": "workspace:*",
|
||||
"is-number": "^7.0.0",
|
||||
},
|
||||
},
|
||||
"packages/b": {
|
||||
"name": "@workspace/b",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"is-odd": "^3.0.1",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@workspace/a": ["@workspace/a@workspace:packages/a"],
|
||||
|
||||
"@workspace/b": ["@workspace/b@workspace:packages/b"],
|
||||
|
||||
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
||||
|
||||
"is-odd": ["is-odd@3.0.1", "", { "dependencies": { "is-number": "^6.0.0" } }, "sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA=="],
|
||||
|
||||
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
|
||||
|
||||
"is-odd/is-number": ["is-number@6.0.0", "", {}, "sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg=="],
|
||||
}
|
||||
}
|
||||
"
|
||||
@@ -272,15 +297,15 @@ exports[`yarn.lock migration basic migration with realistic complex yarn.lock: c
|
||||
"": {
|
||||
"name": "complex-app",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"@babel/core": "^7.20.0",
|
||||
"webpack": "^5.75.0",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.0",
|
||||
"typescript": "^4.9.0",
|
||||
"eslint": "^8.0.0",
|
||||
"typescript": "^4.9.0",
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "^2.3.2",
|
||||
@@ -2932,7 +2957,7 @@ exports[`bun pm migrate for existing yarn.lock yarn-cli-repo: yarn-cli-repo 1`]
|
||||
|
||||
"class-utils/define-property/is-descriptor/is-data-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="],
|
||||
|
||||
"commitizen/inquirer/cli-cursor/restore-cursor/onetime": ["onetime@1.1.0", "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789", {}, "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k="],
|
||||
"commitizen/inquirer/cli-cursor/restore-cursor/onetime": ["onetime@1.1.0", "", {}, "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k="],
|
||||
|
||||
"eslint/inquirer/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="],
|
||||
|
||||
@@ -3141,9 +3166,9 @@ exports[`bun pm migrate for existing yarn.lock yarn-stuff: yarn-stuff 1`] = `
|
||||
"packages": {
|
||||
"abbrev": ["abbrev@1.1.1", "", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="],
|
||||
|
||||
"full-git-url": ["abbrev-js@github:isaacs/abbrev-js#3f9802e", {}, ""],
|
||||
"full-git-url": ["full-git-url@github:isaacs/abbrev-js#3f9802e", {}, ""],
|
||||
|
||||
"ghshort": ["ghshort@3.0.1", "https://codeload.github.com/isaacs/abbrev-js/tar.gz/3f9802e56ff878761a338e43ecacbfed39d2181d", {}, ""],
|
||||
"ghshort": ["ghshort@github:isaacs/abbrev-js#3f9802e", {}, ""],
|
||||
|
||||
"old": ["abbrev@1.0.9", "", {}, "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q=="],
|
||||
|
||||
@@ -3151,11 +3176,11 @@ exports[`bun pm migrate for existing yarn.lock yarn-stuff: yarn-stuff 1`] = `
|
||||
|
||||
"reg": ["abbrev@1.1.1", "", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="],
|
||||
|
||||
"remote": ["abbrev@https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8", {}],
|
||||
"remote": ["abbrev@1.1.1", "", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="],
|
||||
|
||||
"symlink": ["symlink@file:./abbrev-link-target", {}],
|
||||
|
||||
"tarball": ["tarball@abbrev-1.1.1.tgz", {}],
|
||||
"tarball": ["tarball@file:abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8", {}],
|
||||
}
|
||||
}
|
||||
"
|
||||
@@ -3183,8 +3208,8 @@ exports[`bun pm migrate for existing yarn.lock yarn.lock with packages that have
|
||||
"": {
|
||||
"name": "os-cpu-test",
|
||||
"dependencies": {
|
||||
"fsevents": "^2.3.2",
|
||||
"esbuild": "^0.17.0",
|
||||
"fsevents": "^2.3.2",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -3206,3 +3231,135 @@ exports[`bun pm migrate for existing yarn.lock yarn.lock with packages that have
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`bun pm migrate for existing yarn.lock yarn.lock with custom registry tarball URLs: custom-registry-yarn-migration 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "custom-registry-test",
|
||||
"dependencies": {
|
||||
"another-pkg": "https://packages.example.com/tarballs/another-pkg-2.1.0.tgz",
|
||||
"my-package": "https://my-custom-registry.com/my-package/-/my-package-1.0.0.tgz",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"another-pkg": ["another-pkg@2.1.0", "https://packages.example.com/tarballs/another-pkg-2.1.0.tgz", {}, "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="],
|
||||
|
||||
"my-package": ["my-package@1.0.0", "https://my-custom-registry.com/my-package/-/my-package-1.0.0.tgz", {}, ""],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`bun pm migrate for existing yarn.lock all yarn v1 quirks in one test: yarn-comprehensive 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "yarn-quirks-test",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
"@prisma/engines": "4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81",
|
||||
"is-number": "^7.0.0",
|
||||
"my-lodash": "npm:lodash@4.17.21",
|
||||
},
|
||||
"devDependencies": {
|
||||
"lodash": "^3.10.0",
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "^2.3.2",
|
||||
},
|
||||
},
|
||||
"packages/app": {
|
||||
"name": "@workspace/app",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@workspace/lib": "workspace:*",
|
||||
"is-number": "~7.0.0",
|
||||
"lodash": "^4.17.0",
|
||||
},
|
||||
},
|
||||
"packages/lib": {
|
||||
"name": "@workspace/lib",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"is-odd": "^3.0.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@babel/core": ["@babel/core@7.20.12", "", { "dependencies": { "@babel/types": "^7.20.7" } }, "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg=="],
|
||||
|
||||
"@babel/types": ["@babel/types@7.20.7", "", {}, "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg=="],
|
||||
|
||||
"@prisma/engines": ["@prisma/engines@4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81", "", {}, "sha512-q617EUWfRIDTriWADZ4YiWRZXCa/WuhNgLTVd+HqWLffjMSPzyM5uOWoauX91wvQClSKZU4pzI4JJLQ9Kl62Qg=="],
|
||||
|
||||
"@workspace/app": ["@workspace/app@workspace:packages/app"],
|
||||
|
||||
"@workspace/lib": ["@workspace/lib@workspace:packages/lib"],
|
||||
|
||||
"fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],
|
||||
|
||||
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
||||
|
||||
"is-odd": ["is-odd@3.0.1", "", { "dependencies": { "is-number": "^6.0.0" } }, "sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA=="],
|
||||
|
||||
"lodash": ["lodash@3.10.1", "", {}, "sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkSTbUYwRa7cmPR8CKkkl+OuU/fGTM48FNhQ5GnLsXw=="],
|
||||
|
||||
"my-lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
|
||||
|
||||
"@workspace/app/lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
|
||||
|
||||
"is-odd/is-number": ["is-number@6.0.0", "", {}, "sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg=="],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`bun pm migrate for existing yarn.lock parser handles indentation correctly: yarn-indentation 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "indent-test",
|
||||
"dependencies": {
|
||||
"test-pkg": "^1.0.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"dep-a": ["dep-a@1.0.0", "", {}, ""],
|
||||
|
||||
"dep-b": ["dep-b@2.0.0", "", {}, ""],
|
||||
|
||||
"test-pkg": ["test-pkg@1.0.0", "", { "dependencies": { "dep-a": "^1.0.0", "dep-b": "^2.0.0" } }, ""],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`bun pm migrate for existing yarn.lock handles optionalDependencies correctly: yarn-optional-deps 1`] = `
|
||||
"{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "optional-test",
|
||||
"dependencies": {
|
||||
"pkg-a": "^1.0.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"optional-dep": ["optional-dep@1.0.0", "", {}, "sha512-testopt2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="],
|
||||
|
||||
"pkg-a": ["pkg-a@1.0.0", "", { "optionalDependencies": { "optional-dep": "^1.0.0" } }, "sha512-testoptionalAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="],
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
1152
test/cli/install/migration/yarn-berry.test.ts
Normal file
1152
test/cli/install/migration/yarn-berry.test.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,11 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import fs from "fs";
|
||||
import { bunEnv, bunExe, tempDirWithFiles } from "harness";
|
||||
import { bunEnv, bunExe, tempDir } from "harness";
|
||||
import { join } from "path";
|
||||
|
||||
describe("yarn.lock migration basic", () => {
|
||||
test("simple yarn.lock migration produces correct bun.lock", async () => {
|
||||
const tempDir = tempDirWithFiles("yarn-migration-simple", {
|
||||
using dir = tempDir("yarn-migration-simple", {
|
||||
"package.json": JSON.stringify(
|
||||
{
|
||||
name: "simple-test",
|
||||
@@ -31,7 +31,7 @@ is-number@^7.0.0:
|
||||
// Run bun pm migrate
|
||||
const migrateResult = await Bun.spawn({
|
||||
cmd: [bunExe(), "pm", "migrate", "-f"],
|
||||
cwd: tempDir,
|
||||
cwd: String(dir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
@@ -45,14 +45,14 @@ is-number@^7.0.0:
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);
|
||||
expect(fs.existsSync(join(String(dir), "bun.lock"))).toBe(true);
|
||||
|
||||
const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");
|
||||
const bunLockContent = fs.readFileSync(join(String(dir), "bun.lock"), "utf8");
|
||||
expect(bunLockContent).toMatchSnapshot("simple-yarn-migration");
|
||||
});
|
||||
|
||||
test("yarn.lock with packages containing long build tags", async () => {
|
||||
const tempDir = tempDirWithFiles("yarn-migration-build-tags", {
|
||||
using dir = tempDir("yarn-migration-build-tags", {
|
||||
"package.json": JSON.stringify(
|
||||
{
|
||||
name: "build-tags-test",
|
||||
@@ -128,7 +128,7 @@ to-fast-properties@^2.0.0:
|
||||
// Run bun pm migrate
|
||||
const migrateResult = await Bun.spawn({
|
||||
cmd: [bunExe(), "pm", "migrate", "-f"],
|
||||
cwd: tempDir,
|
||||
cwd: String(dir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
@@ -142,9 +142,9 @@ to-fast-properties@^2.0.0:
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);
|
||||
expect(fs.existsSync(join(String(dir), "bun.lock"))).toBe(true);
|
||||
|
||||
const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");
|
||||
const bunLockContent = fs.readFileSync(join(String(dir), "bun.lock"), "utf8");
|
||||
|
||||
// Verify that long build tags are preserved correctly
|
||||
expect(bunLockContent).toContain("4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81");
|
||||
@@ -159,7 +159,7 @@ to-fast-properties@^2.0.0:
|
||||
// Install should work after migration
|
||||
const installResult = await Bun.spawn({
|
||||
cmd: [bunExe(), "install"],
|
||||
cwd: tempDir,
|
||||
cwd: String(dir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
@@ -171,7 +171,7 @@ to-fast-properties@^2.0.0:
|
||||
});
|
||||
|
||||
test("yarn.lock with extremely long build tags (regression test)", async () => {
|
||||
const tempDir = tempDirWithFiles("yarn-migration-extreme-build-tags", {
|
||||
using dir = tempDir("yarn-migration-extreme-build-tags", {
|
||||
"package.json": JSON.stringify(
|
||||
{
|
||||
name: "extreme-build-tags-test",
|
||||
@@ -198,7 +198,7 @@ test-package@1.0.0-alpha.beta.gamma.delta.epsilon.zeta.eta.theta.iota.kappa.lamb
|
||||
// Run bun pm migrate
|
||||
const migrateResult = await Bun.spawn({
|
||||
cmd: [bunExe(), "pm", "migrate", "-f"],
|
||||
cwd: tempDir,
|
||||
cwd: String(dir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
@@ -208,7 +208,7 @@ test-package@1.0.0-alpha.beta.gamma.delta.epsilon.zeta.eta.theta.iota.kappa.lamb
|
||||
const exitCode = await migrateResult.exited;
|
||||
expect(exitCode).toBe(0);
|
||||
|
||||
const bunLockPath = join(tempDir, "bun.lock");
|
||||
const bunLockPath = join(String(dir), "bun.lock");
|
||||
expect(fs.existsSync(bunLockPath)).toBe(true);
|
||||
|
||||
const bunLockContent = fs.readFileSync(bunLockPath, "utf8");
|
||||
@@ -226,7 +226,7 @@ test-package@1.0.0-alpha.beta.gamma.delta.epsilon.zeta.eta.theta.iota.kappa.lamb
|
||||
});
|
||||
|
||||
test("complex yarn.lock with multiple dependencies and versions", async () => {
|
||||
const tempDir = tempDirWithFiles("yarn-migration-complex", {
|
||||
using dir = tempDir("yarn-migration-complex", {
|
||||
"package.json": JSON.stringify(
|
||||
{
|
||||
name: "complex-test",
|
||||
@@ -714,7 +714,7 @@ vary@~1.1.2:
|
||||
// Run bun pm migrate
|
||||
const migrateResult = await Bun.spawn({
|
||||
cmd: [bunExe(), "pm", "migrate", "-f"],
|
||||
cwd: tempDir,
|
||||
cwd: String(dir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
@@ -728,14 +728,14 @@ vary@~1.1.2:
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);
|
||||
expect(fs.existsSync(join(String(dir), "bun.lock"))).toBe(true);
|
||||
|
||||
const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");
|
||||
const bunLockContent = fs.readFileSync(join(String(dir), "bun.lock"), "utf8");
|
||||
expect(bunLockContent).toMatchSnapshot("complex-yarn-migration");
|
||||
});
|
||||
|
||||
test("yarn.lock with npm aliases", async () => {
|
||||
const tempDir = tempDirWithFiles("yarn-migration-aliases", {
|
||||
using dir = tempDir("yarn-migration-aliases", {
|
||||
"package.json": JSON.stringify(
|
||||
{
|
||||
name: "alias-test",
|
||||
@@ -786,7 +786,7 @@ undici-types@~5.26.4:
|
||||
// Run bun pm migrate
|
||||
const migrateResult = await Bun.spawn({
|
||||
cmd: [bunExe(), "pm", "migrate", "-f"],
|
||||
cwd: tempDir,
|
||||
cwd: String(dir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
@@ -800,9 +800,9 @@ undici-types@~5.26.4:
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);
|
||||
expect(fs.existsSync(join(String(dir), "bun.lock"))).toBe(true);
|
||||
|
||||
const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");
|
||||
const bunLockContent = fs.readFileSync(join(String(dir), "bun.lock"), "utf8");
|
||||
expect(bunLockContent).toMatchSnapshot("aliases-yarn-migration");
|
||||
|
||||
// Verify that npm aliases are handled correctly
|
||||
@@ -811,7 +811,7 @@ undici-types@~5.26.4:
|
||||
});
|
||||
|
||||
test("yarn.lock with resolutions", async () => {
|
||||
const tempDir = tempDirWithFiles("yarn-migration-resolutions", {
|
||||
using dir = tempDir("yarn-migration-resolutions", {
|
||||
"package.json": JSON.stringify(
|
||||
{
|
||||
name: "resolutions-test",
|
||||
@@ -876,7 +876,7 @@ webpack@^5.89.0:
|
||||
// Run bun pm migrate
|
||||
const migrateResult = await Bun.spawn({
|
||||
cmd: [bunExe(), "pm", "migrate", "-f"],
|
||||
cwd: tempDir,
|
||||
cwd: String(dir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
@@ -890,9 +890,9 @@ webpack@^5.89.0:
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);
|
||||
expect(fs.existsSync(join(String(dir), "bun.lock"))).toBe(true);
|
||||
|
||||
const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");
|
||||
const bunLockContent = fs.readFileSync(join(String(dir), "bun.lock"), "utf8");
|
||||
expect(bunLockContent).toMatchSnapshot("resolutions-yarn-migration");
|
||||
|
||||
// Verify resolutions are handled
|
||||
@@ -900,7 +900,7 @@ webpack@^5.89.0:
|
||||
});
|
||||
|
||||
test("yarn.lock with workspace dependencies", async () => {
|
||||
const tempDir = tempDirWithFiles("yarn-migration-workspace", {
|
||||
using dir = tempDir("yarn-migration-workspace", {
|
||||
"package.json": JSON.stringify(
|
||||
{
|
||||
name: "workspace-root",
|
||||
@@ -974,7 +974,7 @@ lodash@^4.17.21:
|
||||
// Run bun pm migrate
|
||||
const migrateResult = await Bun.spawn({
|
||||
cmd: [bunExe(), "pm", "migrate", "-f"],
|
||||
cwd: tempDir,
|
||||
cwd: String(dir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
@@ -988,9 +988,9 @@ lodash@^4.17.21:
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);
|
||||
expect(fs.existsSync(join(String(dir), "bun.lock"))).toBe(true);
|
||||
|
||||
const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");
|
||||
const bunLockContent = fs.readFileSync(join(String(dir), "bun.lock"), "utf8");
|
||||
expect(bunLockContent).toMatchSnapshot("workspace-yarn-migration");
|
||||
|
||||
// TODO: Workspace dependencies are not yet supported in yarn migration
|
||||
@@ -998,7 +998,7 @@ lodash@^4.17.21:
|
||||
});
|
||||
|
||||
test("yarn.lock with scoped packages and parent/child relationships", async () => {
|
||||
const tempDir = tempDirWithFiles("yarn-migration-scoped", {
|
||||
using dir = tempDir("yarn-migration-scoped", {
|
||||
"package.json": JSON.stringify(
|
||||
{
|
||||
name: "scoped-test",
|
||||
@@ -1089,7 +1089,7 @@ babel-loader/chalk@^2.4.2:
|
||||
// Run bun pm migrate
|
||||
const migrateResult = await Bun.spawn({
|
||||
cmd: [bunExe(), "pm", "migrate", "-f"],
|
||||
cwd: tempDir,
|
||||
cwd: String(dir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
@@ -1103,9 +1103,9 @@ babel-loader/chalk@^2.4.2:
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);
|
||||
expect(fs.existsSync(join(String(dir), "bun.lock"))).toBe(true);
|
||||
|
||||
const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");
|
||||
const bunLockContent = fs.readFileSync(join(String(dir), "bun.lock"), "utf8");
|
||||
expect(bunLockContent).toMatchSnapshot("scoped-yarn-migration");
|
||||
|
||||
// Verify scoped packages are at the bottom
|
||||
@@ -1124,7 +1124,7 @@ babel-loader/chalk@^2.4.2:
|
||||
|
||||
test("migration with realistic complex yarn.lock", async () => {
|
||||
// Create a realistic yarn.lock with various edge cases
|
||||
const tempDir = tempDirWithFiles("yarn-migration-complex-realistic", {
|
||||
using dir = tempDir("yarn-migration-complex-realistic", {
|
||||
"package.json": JSON.stringify(
|
||||
{
|
||||
name: "complex-app",
|
||||
@@ -1314,7 +1314,7 @@ webpack@^5.75.0:
|
||||
// Run bun pm migrate
|
||||
const migrateResult = await Bun.spawn({
|
||||
cmd: [bunExe(), "pm", "migrate", "-f"],
|
||||
cwd: tempDir,
|
||||
cwd: String(dir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
@@ -1323,9 +1323,9 @@ webpack@^5.75.0:
|
||||
|
||||
const exitCode = await migrateResult.exited;
|
||||
expect(exitCode).toBe(0);
|
||||
expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);
|
||||
expect(fs.existsSync(join(String(dir), "bun.lock"))).toBe(true);
|
||||
|
||||
const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");
|
||||
const bunLockContent = fs.readFileSync(join(String(dir), "bun.lock"), "utf8");
|
||||
expect(bunLockContent).toMatchSnapshot("complex-realistic-yarn-migration");
|
||||
|
||||
// Verify key features are migrated
|
||||
@@ -1352,14 +1352,14 @@ describe("bun pm migrate for existing yarn.lock", () => {
|
||||
const packageJsonContent = await Bun.file(join(import.meta.dir, "yarn", folder, "package.json")).text();
|
||||
const yarnLockContent = await Bun.file(join(import.meta.dir, "yarn", folder, "yarn.lock")).text();
|
||||
|
||||
const tempDir = tempDirWithFiles("yarn-lock-migration-", {
|
||||
using dir = tempDir("yarn-lock-migration-", {
|
||||
"package.json": packageJsonContent,
|
||||
"yarn.lock": yarnLockContent,
|
||||
});
|
||||
|
||||
const migrateResult = Bun.spawn({
|
||||
cmd: [bunExe(), "pm", "migrate", "-f"],
|
||||
cwd: tempDir,
|
||||
cwd: String(dir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
@@ -1367,14 +1367,14 @@ describe("bun pm migrate for existing yarn.lock", () => {
|
||||
});
|
||||
|
||||
expect(migrateResult.exited).resolves.toBe(0);
|
||||
expect(Bun.file(join(tempDir, "bun.lock")).exists()).resolves.toBe(true);
|
||||
expect(Bun.file(join(String(dir), "bun.lock")).exists()).resolves.toBe(true);
|
||||
|
||||
const bunLockContent = await Bun.file(join(tempDir, "bun.lock")).text();
|
||||
const bunLockContent = await Bun.file(join(String(dir), "bun.lock")).text();
|
||||
expect(bunLockContent).toMatchSnapshot(folder);
|
||||
});
|
||||
|
||||
test("yarn.lock with packages that have os/cpu requirements", async () => {
|
||||
const tempDir = tempDirWithFiles("yarn-migration-os-cpu", {
|
||||
using dir = tempDir("yarn-migration-os-cpu", {
|
||||
"package.json": JSON.stringify(
|
||||
{
|
||||
name: "os-cpu-test",
|
||||
@@ -1454,7 +1454,7 @@ fsevents@^2.3.2:
|
||||
// Run bun pm migrate
|
||||
const migrateResult = await Bun.spawn({
|
||||
cmd: [bunExe(), "pm", "migrate", "-f"],
|
||||
cwd: tempDir,
|
||||
cwd: String(dir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
@@ -1468,9 +1468,9 @@ fsevents@^2.3.2:
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true);
|
||||
expect(fs.existsSync(join(String(dir), "bun.lock"))).toBe(true);
|
||||
|
||||
const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8");
|
||||
const bunLockContent = fs.readFileSync(join(String(dir), "bun.lock"), "utf8");
|
||||
expect(bunLockContent).toMatchSnapshot("os-cpu-yarn-migration");
|
||||
|
||||
// Verify that the lockfile contains the expected os/cpu metadata by checking the snapshot
|
||||
@@ -1479,4 +1479,328 @@ fsevents@^2.3.2:
|
||||
expect(bunLockContent).toContain("@esbuild/linux-arm64");
|
||||
expect(bunLockContent).toContain("@esbuild/darwin-arm64");
|
||||
});
|
||||
|
||||
test("yarn.lock with custom registry tarball URLs", async () => {
|
||||
using dir = tempDir("yarn-migration-custom-registry", {
|
||||
"package.json": JSON.stringify(
|
||||
{
|
||||
name: "custom-registry-test",
|
||||
version: "1.0.0",
|
||||
dependencies: {
|
||||
"my-package": "https://my-custom-registry.com/my-package/-/my-package-1.0.0.tgz",
|
||||
"another-pkg": "https://packages.example.com/tarballs/another-pkg-2.1.0.tgz",
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
"yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"another-pkg@https://packages.example.com/tarballs/another-pkg-2.1.0.tgz":
|
||||
version "2.1.0"
|
||||
resolved "https://packages.example.com/tarballs/another-pkg-2.1.0.tgz#abc123def456"
|
||||
integrity sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
|
||||
|
||||
"my-package@https://my-custom-registry.com/my-package/-/my-package-1.0.0.tgz":
|
||||
version "1.0.0"
|
||||
resolved "https://my-custom-registry.com/my-package/-/my-package-1.0.0.tgz#deadbeef"
|
||||
integrity sha512-BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=
|
||||
`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "pm", "migrate", "-f"],
|
||||
cwd: String(dir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
||||
|
||||
expect(stderr).not.toContain("error");
|
||||
expect(exitCode).toBe(0);
|
||||
|
||||
const bunLockContent = await Bun.file(join(String(dir), "bun.lock")).text();
|
||||
expect(bunLockContent).toMatchSnapshot("custom-registry-yarn-migration");
|
||||
|
||||
// Verify custom registry URLs are preserved as tarball resolutions
|
||||
expect(bunLockContent).toContain("my-package");
|
||||
expect(bunLockContent).toContain("another-pkg");
|
||||
expect(bunLockContent).toContain("my-custom-registry.com");
|
||||
expect(bunLockContent).toContain("packages.example.com");
|
||||
});
|
||||
|
||||
test("all yarn v1 quirks in one test", async () => {
|
||||
using dir = tempDir("yarn-comprehensive", {
|
||||
"package.json": JSON.stringify(
|
||||
{
|
||||
name: "yarn-quirks-test",
|
||||
version: "1.0.0",
|
||||
private: true,
|
||||
workspaces: ["packages/*"],
|
||||
dependencies: {
|
||||
// Multi-spec consolidation: multiple ranges -> same version
|
||||
"is-number": "^7.0.0",
|
||||
// npm alias
|
||||
"my-lodash": "npm:lodash@4.17.21",
|
||||
// Scoped package
|
||||
"@babel/core": "^7.20.0",
|
||||
// Long build tag
|
||||
"@prisma/engines": "4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81",
|
||||
},
|
||||
devDependencies: {
|
||||
// Multiple versions of same package
|
||||
lodash: "^3.10.0",
|
||||
},
|
||||
optionalDependencies: {
|
||||
// Platform-specific (but yarn doesn't store os/cpu)
|
||||
fsevents: "^2.3.2",
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
"packages/app/package.json": JSON.stringify(
|
||||
{
|
||||
name: "@workspace/app",
|
||||
version: "1.0.0",
|
||||
dependencies: {
|
||||
// Workspace dependency
|
||||
"@workspace/lib": "workspace:*",
|
||||
// Creates multi-spec entry with root
|
||||
"is-number": "~7.0.0",
|
||||
// Different version than root
|
||||
lodash: "^4.17.0",
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
"packages/lib/package.json": JSON.stringify(
|
||||
{
|
||||
name: "@workspace/lib",
|
||||
version: "1.0.0",
|
||||
dependencies: {
|
||||
// External dep
|
||||
"is-odd": "^3.0.0",
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
"yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@babel/core@^7.20.0":
|
||||
version "7.20.12"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.12.tgz#7f12f7fe01cfcc5c4f37fa6e09a6e7ac0736b5e9"
|
||||
integrity sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==
|
||||
dependencies:
|
||||
"@babel/types" "^7.20.7"
|
||||
|
||||
"@babel/types@^7.20.7":
|
||||
version "7.20.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.7.tgz#54ec75e252318423fc07fb644dc6a58a64c09b7f"
|
||||
integrity sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==
|
||||
|
||||
"@prisma/engines@4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81":
|
||||
version "4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81.tgz#5512069ca14c44af7f38e7c39d9a169480e63a33"
|
||||
integrity sha512-q617EUWfRIDTriWADZ4YiWRZXCa/WuhNgLTVd+HqWLffjMSPzyM5uOWoauX91wvQClSKZU4pzI4JJLQ9Kl62Qg==
|
||||
|
||||
"@workspace/lib@workspace:*, @workspace/lib@workspace:packages/lib":
|
||||
version "0.0.0-use.local"
|
||||
resolved "file:packages/lib"
|
||||
dependencies:
|
||||
is-odd "^3.0.0"
|
||||
|
||||
fsevents@^2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
||||
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
|
||||
|
||||
"is-number@^6.0.0":
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-6.0.0.tgz#e6d15ad31fc262887d1846d1c6c84c9b3b0b5982"
|
||||
integrity sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==
|
||||
|
||||
"is-number@^7.0.0, is-number@~7.0.0":
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||
|
||||
is-odd@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-3.0.1.tgz#65101baf63c59f7b5c3a429d0a4e3d8ca7914559"
|
||||
integrity sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA==
|
||||
dependencies:
|
||||
is-number "^6.0.0"
|
||||
|
||||
lodash@^3.10.0:
|
||||
version "3.10.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
|
||||
integrity sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkSTbUYwRa7cmPR8CKkkl+OuU/fGTM48FNhQ5GnLsXw==
|
||||
|
||||
"lodash@^4.17.0, lodash@4.17.21":
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
||||
my-lodash@npm:lodash@4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "pm", "migrate", "-f"],
|
||||
cwd: String(dir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
||||
|
||||
expect(stderr).not.toContain("error");
|
||||
expect(exitCode).toBe(0);
|
||||
|
||||
const bunLockContent = await Bun.file(join(String(dir), "bun.lock")).text();
|
||||
expect(bunLockContent).toMatchSnapshot("yarn-comprehensive");
|
||||
|
||||
// Multi-spec consolidation: both specs resolve to same package
|
||||
expect(bunLockContent).toContain("is-number@7.0.0");
|
||||
|
||||
// npm alias: should create entry for alias pointing to real package
|
||||
expect(bunLockContent).toContain("my-lodash");
|
||||
expect(bunLockContent).toContain("lodash@4.17.21");
|
||||
|
||||
// Multiple versions: both lodash 3 and 4 should exist
|
||||
expect(bunLockContent).toContain("lodash@3.10.1");
|
||||
|
||||
// Long build tag preserved
|
||||
expect(bunLockContent).toContain("4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81");
|
||||
|
||||
// Scoped packages
|
||||
expect(bunLockContent).toContain("@babel/core");
|
||||
expect(bunLockContent).toContain("@babel/types");
|
||||
|
||||
// Workspace dependencies
|
||||
expect(bunLockContent).toContain("@workspace/app");
|
||||
expect(bunLockContent).toContain("@workspace/lib");
|
||||
|
||||
// Integrity hashes preserved
|
||||
expect(bunLockContent).toMatch(/sha512-/);
|
||||
});
|
||||
|
||||
test("parser handles indentation correctly", async () => {
|
||||
// Test that the parser correctly handles the YAML-like indentation
|
||||
using dir = tempDir("yarn-indentation", {
|
||||
"package.json": JSON.stringify(
|
||||
{
|
||||
name: "indent-test",
|
||||
version: "1.0.0",
|
||||
dependencies: {
|
||||
"test-pkg": "^1.0.0",
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
"yarn.lock": `# yarn lockfile v1
|
||||
|
||||
test-pkg@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/test-pkg/-/test-pkg-1.0.0.tgz#abc123"
|
||||
integrity sha512-test123==
|
||||
dependencies:
|
||||
dep-a "^1.0.0"
|
||||
dep-b "^2.0.0"
|
||||
|
||||
dep-a@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/dep-a/-/dep-a-1.0.0.tgz#def456"
|
||||
integrity sha512-testa==
|
||||
|
||||
dep-b@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/dep-b/-/dep-b-2.0.0.tgz#ghi789"
|
||||
integrity sha512-testb==
|
||||
`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "pm", "migrate", "-f"],
|
||||
cwd: String(dir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
||||
|
||||
expect(stderr).not.toContain("error");
|
||||
expect(exitCode).toBe(0);
|
||||
|
||||
const bunLockContent = await Bun.file(join(String(dir), "bun.lock")).text();
|
||||
expect(bunLockContent).toMatchSnapshot("yarn-indentation");
|
||||
expect(bunLockContent).toContain("test-pkg");
|
||||
expect(bunLockContent).toContain("dep-a");
|
||||
expect(bunLockContent).toContain("dep-b");
|
||||
});
|
||||
|
||||
test("handles optionalDependencies correctly", async () => {
|
||||
using dir = tempDir("yarn-optional", {
|
||||
"package.json": JSON.stringify(
|
||||
{
|
||||
name: "optional-test",
|
||||
version: "1.0.0",
|
||||
dependencies: {
|
||||
"pkg-a": "^1.0.0",
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
"yarn.lock": `# yarn lockfile v1
|
||||
|
||||
pkg-a@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pkg-a/-/pkg-a-1.0.0.tgz#abc"
|
||||
integrity sha512-testoptional==
|
||||
optionalDependencies:
|
||||
optional-dep "^1.0.0"
|
||||
|
||||
optional-dep@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/optional-dep/-/optional-dep-1.0.0.tgz#def"
|
||||
integrity sha512-testopt2==
|
||||
`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "pm", "migrate", "-f"],
|
||||
cwd: String(dir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
||||
|
||||
expect(stderr).not.toContain("error");
|
||||
expect(exitCode).toBe(0);
|
||||
|
||||
const bunLockContent = await Bun.file(join(String(dir), "bun.lock")).text();
|
||||
expect(bunLockContent).toMatchSnapshot("yarn-optional-deps");
|
||||
expect(bunLockContent).toContain("pkg-a");
|
||||
expect(bunLockContent).toContain("optional-dep");
|
||||
// Should have optionalDependencies field in metadata
|
||||
expect(bunLockContent).toMatch(/optionalDependencies/);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user