diff options
Diffstat (limited to 'src/install/install.zig')
-rw-r--r-- | src/install/install.zig | 57 |
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), |