aboutsummaryrefslogtreecommitdiff
path: root/src/install/install.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/install/install.zig')
-rw-r--r--src/install/install.zig57
1 files changed, 45 insertions, 12 deletions
diff --git a/src/install/install.zig b/src/install/install.zig
index 52025aa04..06eb7296e 100644
--- a/src/install/install.zig
+++ b/src/install/install.zig
@@ -1628,6 +1628,7 @@ const NetworkChannel = sync.Channel(*NetworkTask, .{ .Static = 8192 });
const ThreadPool = bun.ThreadPool;
const PackageManifestMap = std.HashMapUnmanaged(PackageNameHash, Npm.PackageManifest, IdentityContext(PackageNameHash), 80);
const RepositoryMap = std.HashMapUnmanaged(u64, bun.FileDescriptor, IdentityContext(u64), 80);
+const NpmAliasMap = std.HashMapUnmanaged(PackageNameHash, Dependency.Version, IdentityContext(u64), 80);
pub const CacheLevel = struct {
use_cache_control_headers: bool,
@@ -1754,6 +1755,9 @@ pub const PackageManager = struct {
uws_event_loop: *uws.Loop,
file_poll_store: JSC.FilePoll.Store,
+ // name hash from alias package name -> aliased package dependency version info
+ known_npm_aliases: NpmAliasMap = .{},
+
const PreallocatedNetworkTasks = std.BoundedArray(NetworkTask, 1024);
const NetworkTaskQueue = std.HashMapUnmanaged(u64, void, IdentityContext(u64), 80);
pub var verbose_install = false;
@@ -3063,20 +3067,47 @@ pub const PackageManager = struct {
.dist_tag, .git, .github, .npm, .tarball, .workspace => String.Builder.stringHash(this.lockfile.str(&name)),
else => dependency.name_hash,
};
+
const version = version: {
- if (this.lockfile.overrides.get(name_hash)) |new| {
- debug("override: {s} -> {s}", .{ this.lockfile.str(&dependency.version.literal), this.lockfile.str(&new.literal) });
- name = switch (new.tag) {
- .dist_tag => new.value.dist_tag.name,
- .git => new.value.git.package_name,
- .github => new.value.github.package_name,
- .npm => new.value.npm.name,
- .tarball => new.value.tarball.package_name,
- else => name,
- };
- name_hash = String.Builder.stringHash(this.lockfile.str(&name));
- break :version new;
+ if (dependency.version.tag == .npm) {
+ if (this.known_npm_aliases.get(name_hash)) |aliased| {
+ const group = dependency.version.value.npm.version;
+ var curr_list: ?*const Semver.Query.List = &aliased.value.npm.version.head;
+ while (curr_list) |queries| {
+ var curr: ?*const Semver.Query = &queries.head;
+ while (curr) |query| {
+ if (group.satisfies(query.range.left.version) or group.satisfies(query.range.right.version)) {
+ name = aliased.value.npm.name;
+ name_hash = String.Builder.stringHash(this.lockfile.str(&name));
+ break :version aliased;
+ }
+ curr = query.next;
+ }
+ curr_list = queries.next;
+ }
+
+ // fallthrough. a package that matches the name of an alias but does not match
+ // the version should be enqueued as a normal npm dependency, overrides allowed
+ }
}
+
+ // allow overriding all dependencies unless the dependency is coming directly from an alias, "npm:<this dep>"
+ if (dependency.version.tag != .npm or !dependency.version.value.npm.is_alias) {
+ if (this.lockfile.overrides.get(name_hash)) |new| {
+ debug("override: {s} -> {s}", .{ this.lockfile.str(&dependency.version.literal), this.lockfile.str(&new.literal) });
+ name = switch (new.tag) {
+ .dist_tag => new.value.dist_tag.name,
+ .git => new.value.git.package_name,
+ .github => new.value.github.package_name,
+ .npm => new.value.npm.name,
+ .tarball => new.value.tarball.package_name,
+ else => name,
+ };
+ name_hash = String.Builder.stringHash(this.lockfile.str(&name));
+ break :version new;
+ }
+ }
+
break :version dependency.version;
};
var loaded_manifest: ?Npm.PackageManifest = null;
@@ -6386,6 +6417,7 @@ pub const PackageManager = struct {
var version = Dependency.parseWithOptionalTag(
allocator,
if (alias) |name| String.init(input, name) else placeholder,
+ if (alias) |name| String.Builder.stringHash(name) else null,
value,
null,
&SlicedString.init(input, value),
@@ -6400,6 +6432,7 @@ pub const PackageManager = struct {
if (Dependency.parseWithOptionalTag(
allocator,
placeholder,
+ null,
input,
null,
&SlicedString.init(input, input),