diff --git a/Cargo.lock b/Cargo.lock index 91f165b..268689c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2050,8 +2050,8 @@ dependencies = [ "serde_json", "sha2", "tokio", - "wit-component", - "wit-parser", + "wit-component 0.219.1", + "wit-parser 0.219.1", ] [[package]] @@ -4097,6 +4097,16 @@ dependencies = [ "wasmparser 0.219.1", ] +[[package]] +name = "wasm-encoder" +version = "0.220.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebf48234b389415b226a4daef6562933d38c7b28a8b8f64c5c4130dad1561ab7" +dependencies = [ + "leb128", + "wasmparser 0.220.0", +] + [[package]] name = "wasm-metadata" version = "0.219.1" @@ -4113,6 +4123,22 @@ dependencies = [ "wasmparser 0.219.1", ] +[[package]] +name = "wasm-metadata" +version = "0.220.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f3e5f5920c5abfc45573c89b07b38efdaae1515ef86f83dad12d60e50ecd62b" +dependencies = [ + "anyhow", + "indexmap 2.6.0", + "serde", + "serde_derive", + "serde_json", + "spdx", + "wasm-encoder 0.220.0", + "wasmparser 0.220.0", +] + [[package]] name = "wasm-pkg-client" version = "0.8.5" @@ -4142,9 +4168,9 @@ dependencies = [ "warg-client", "warg-crypto", "warg-protocol", - "wasm-metadata", + "wasm-metadata 0.220.0", "wasm-pkg-common", - "wit-component", + "wit-component 0.220.0", ] [[package]] @@ -4184,12 +4210,12 @@ dependencies = [ "tokio-util", "toml", "tracing", - "wasm-metadata", + "wasm-metadata 0.220.0", "wasm-pkg-client", "wasm-pkg-common", "windows-sys 0.59.0", - "wit-component", - "wit-parser", + "wit-component 0.220.0", + "wit-parser 0.220.0", ] [[package]] @@ -4229,6 +4255,19 @@ dependencies = [ "semver", ] +[[package]] +name = "wasmparser" +version = "0.220.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e246c2772ce3ebc83f89a2d4487ac5794cad6c309b2071818a88c7db7c36d87b" +dependencies = [ + "ahash", + "bitflags 2.6.0", + "hashbrown 0.14.5", + "indexmap 2.6.0", + "semver", +] + [[package]] name = "wasmprinter" version = "0.2.80" @@ -4521,9 +4560,28 @@ dependencies = [ "serde_derive", "serde_json", "wasm-encoder 0.219.1", - "wasm-metadata", + "wasm-metadata 0.219.1", "wasmparser 0.219.1", - "wit-parser", + "wit-parser 0.219.1", +] + +[[package]] +name = "wit-component" +version = "0.220.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ccedf54cc65f287da268d64d2bf4f7530d2cfb2296ffbe3ad5f65567e4cf53" +dependencies = [ + "anyhow", + "bitflags 2.6.0", + "indexmap 2.6.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder 0.220.0", + "wasm-metadata 0.220.0", + "wasmparser 0.220.0", + "wit-parser 0.220.0", ] [[package]] @@ -4544,6 +4602,24 @@ dependencies = [ "wasmparser 0.219.1", ] +[[package]] +name = "wit-parser" +version = "0.220.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b7117ce3adc0b4354b46dc1cf3190b00b333e65243d244c613ffcc58bdec84d" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.6.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser 0.220.0", +] + [[package]] name = "wkg" version = "0.8.5" @@ -4564,7 +4640,7 @@ dependencies = [ "wasm-pkg-client", "wasm-pkg-common", "wasm-pkg-core", - "wit-component", + "wit-component 0.220.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1741da9..caef9eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ tracing-subscriber = { version = "0.3.18", default-features = false, features = ] } wasm-pkg-common = { version = "0.8.5", path = "crates/wasm-pkg-common" } wasm-pkg-client = { version = "0.8.5", path = "crates/wasm-pkg-client" } +wasm-metadata = "0.220" +wit-component = "0.220" +wit-parser = "0.220" wasm-pkg-core = { version = "0.8.5", path = "crates/wasm-pkg-core" } -wasm-metadata = "0.219" -wit-component = "0.219" -wit-parser = "0.219" diff --git a/crates/wasm-pkg-core/src/lock.rs b/crates/wasm-pkg-core/src/lock.rs index 1bb5a00..a6e4950 100644 --- a/crates/wasm-pkg-core/src/lock.rs +++ b/crates/wasm-pkg-core/src/lock.rs @@ -16,7 +16,7 @@ use tokio::{ }; use wasm_pkg_client::{ContentDigest, PackageRef}; -use crate::resolver::{DependencyResolution, DependencyResolutionMap}; +use crate::resolver::{DependencyResolution, DependencyResolutionMap, DEFAULT_REGISTRY_NAME}; /// The default name of the lock file. pub const LOCK_FILE_NAME: &str = "wkg.lock"; @@ -279,6 +279,17 @@ pub struct LockedPackage { pub versions: Vec, } +impl LockedPackage { + /// Gets the key used in sorting and searching the package list. + pub fn key(&self) -> (&str, &str, &str) { + ( + self.name.namespace().as_ref(), + self.name.name().as_ref(), + self.registry.as_deref().unwrap_or(DEFAULT_REGISTRY_NAME), + ) + } +} + impl Ord for LockedPackage { fn cmp(&self, other: &Self) -> Ordering { if self.name == other.name { @@ -306,6 +317,13 @@ pub struct LockedPackageVersion { pub digest: ContentDigest, } +impl LockedPackageVersion { + /// Gets the sort key for the locked package version. + pub fn key(&self) -> String { + self.requirement.to_string() + } +} + #[derive(Debug, Deserialize)] struct LockFileIntermediate { version: u64, diff --git a/crates/wasm-pkg-core/src/resolver.rs b/crates/wasm-pkg-core/src/resolver.rs index 7704ef3..c9d5e3c 100644 --- a/crates/wasm-pkg-core/src/resolver.rs +++ b/crates/wasm-pkg-core/src/resolver.rs @@ -364,20 +364,22 @@ impl<'a> DependencyResolver<'a> { name: &PackageRef, dependency: &Dependency, ) -> Result<()> { - self.add_dependency_internal(name, dependency, false).await + self.add_dependency_internal(name, dependency, false) + .await } - /// Add a dependency to the resolver. If the dependency already exists, then it will be - /// overridden. - pub async fn override_dependency( + /// Add a concrete component dependency to the resolver. If the dependency already exists, then it will be ignored. + /// To override an existing dependency, use [`override_dependency`](Self::override_dependency). + pub async fn add_shallow_dependency( &mut self, name: &PackageRef, dependency: &Dependency, ) -> Result<()> { - self.add_dependency_internal(name, dependency, true).await + self.add_shallow_dependency_internal(name, dependency, false) + .await } - async fn add_dependency_internal( + async fn add_shallow_dependency_internal( &mut self, name: &PackageRef, dependency: &Dependency, @@ -385,42 +387,93 @@ impl<'a> DependencyResolver<'a> { ) -> Result<()> { match dependency { Dependency::Package(package) => { - // Dependency comes from a registry, add a dependency to the resolver - let registry_name = package.registry.as_deref().or_else(|| { - self.client.client().ok().and_then(|client| { - client - .config() - .resolve_registry(name) - .map(|reg| reg.as_ref()) - }) + self.add_registry_package(name, force_override, package)? + } + Dependency::Local(p) => { + // A local path dependency, insert a resolution immediately + let res = DependencyResolution::Local(LocalResolution { + name: name.clone(), + path: p.clone(), }); - let package_name = package.name.clone().unwrap_or_else(|| name.clone()); - - // Resolve the version from the lock file if there is one - let locked = match self.lock_file.as_ref().and_then(|resolver| { - resolver - .resolve(registry_name, &package_name, &package.version) - .transpose() - }) { - Some(Ok(locked)) => Some(locked), - Some(Err(e)) => return Err(e), - _ => None, - }; - - if !force_override - && (self.resolutions.contains_key(name) || self.dependencies.contains_key(name)) - { + + if !force_override && self.resolutions.contains_key(name) { tracing::debug!(%name, "dependency already exists and override is not set, ignoring"); return Ok(()); } - self.dependencies.insert( - name.to_owned(), - RegistryDependency { - package: package_name, - version: package.version.clone(), - locked: locked.map(|l| (l.version.clone(), l.digest.clone())), - }, - ); + + let prev = self.resolutions.insert(name.clone(), res); + assert!(prev.is_none()); + } + } + + Ok(()) + } + + /// Add a dependency to the resolver. If the dependency already exists, then it will be + /// overridden. + pub async fn override_dependency( + &mut self, + name: &PackageRef, + dependency: &Dependency, + ) -> Result<()> { + self.add_dependency_internal(name, dependency, true) + .await + } + + fn add_registry_package( + &mut self, + name: &PackageRef, + force_override: bool, + package: &RegistryPackage, + ) -> Result<()> { + // Dependency comes from a registry, add a dependency to the resolver + let registry_name = package.registry.as_deref().or_else(|| { + self.client.client().ok().and_then(|client| { + client + .config() + .resolve_registry(name) + .map(|reg| reg.as_ref()) + }) + }); + let package_name = package.name.clone().unwrap_or_else(|| name.clone()); + + // Resolve the version from the lock file if there is one + let locked = match self.lock_file.as_ref().and_then(|resolver| { + resolver + .resolve(registry_name, &package_name, &package.version) + .transpose() + }) { + Some(Ok(locked)) => Some(locked), + Some(Err(e)) => return Err(e), + _ => None, + }; + + if !force_override + && (self.resolutions.contains_key(name) || self.dependencies.contains_key(name)) + { + tracing::debug!(%name, "dependency already exists and override is not set, ignoring"); + return Ok(()); + } + self.dependencies.insert( + name.to_owned(), + RegistryDependency { + package: package_name, + version: package.version.clone(), + locked: locked.map(|l| (l.version.clone(), l.digest.clone())), + }, + ); + Ok(()) + } + + async fn add_dependency_internal( + &mut self, + name: &PackageRef, + dependency: &Dependency, + force_override: bool, + ) -> Result<()> { + match dependency { + Dependency::Package(package) => { + self.add_registry_package(name, force_override, package)? } Dependency::Local(p) => { // A local path dependency, insert a resolution immediately @@ -588,10 +641,11 @@ fn find_latest_release<'a>( versions: &'a [VersionInfo], req: &VersionReq, ) -> Option<&'a VersionInfo> { - versions + let versions = versions .iter() .filter(|info| !info.yanked && req.matches(&info.version)) - .max_by(|a, b| a.version.cmp(&b.version)) + .max_by(|a, b| a.version.cmp(&b.version)); + versions } // NOTE(thomastaylor312): This is copied from the old wit package in the cargo-component and broken