Skip to content

Commit f299395

Browse files
committed
enable cargo-component lock files
1 parent 873e77a commit f299395

File tree

3 files changed

+149
-16
lines changed

3 files changed

+149
-16
lines changed

crates/wasm-pkg-core/src/lock.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use tokio::{
1616
};
1717
use wasm_pkg_client::{ContentDigest, PackageRef};
1818

19-
use crate::resolver::{DependencyResolution, DependencyResolutionMap};
19+
use crate::resolver::{DependencyResolution, DependencyResolutionMap, DEFAULT_REGISTRY_NAME};
2020

2121
/// The default name of the lock file.
2222
pub const LOCK_FILE_NAME: &str = "wkg.lock";
@@ -271,6 +271,17 @@ pub struct LockedPackage {
271271
pub versions: Vec<LockedPackageVersion>,
272272
}
273273

274+
impl LockedPackage {
275+
/// Gets the key used in sorting and searching the package list.
276+
pub fn key(&self) -> (&str, &str, &str) {
277+
(
278+
self.name.namespace().as_ref(),
279+
self.name.name().as_ref(),
280+
self.registry.as_deref().unwrap_or(DEFAULT_REGISTRY_NAME),
281+
)
282+
}
283+
}
284+
274285
impl Ord for LockedPackage {
275286
fn cmp(&self, other: &Self) -> Ordering {
276287
if self.name == other.name {
@@ -298,6 +309,13 @@ pub struct LockedPackageVersion {
298309
pub digest: ContentDigest,
299310
}
300311

312+
impl LockedPackageVersion {
313+
/// Gets the sort key for the locked package version.
314+
pub fn key(&self) -> String {
315+
self.requirement.to_string()
316+
}
317+
}
318+
301319
#[derive(Debug, Deserialize)]
302320
struct LockFileIntermediate {
303321
version: u64,

crates/wasm-pkg-core/src/resolver.rs

Lines changed: 125 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ use anyhow::{bail, Context, Result};
1313
use futures_util::TryStreamExt;
1414
use indexmap::{IndexMap, IndexSet};
1515
use semver::{Comparator, Op, Version, VersionReq};
16+
use serde::{
17+
de::{self, value::MapAccessDeserializer},
18+
Deserialize, Serialize,
19+
};
1620
use tokio::io::{AsyncRead, AsyncReadExt};
1721
use wasm_pkg_client::{
1822
caching::{CachingClient, FileCache},
@@ -38,6 +42,108 @@ pub enum Dependency {
3842
Local(PathBuf),
3943
}
4044

45+
impl Serialize for Dependency {
46+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
47+
where
48+
S: serde::Serializer,
49+
{
50+
match self {
51+
Self::Package(package) => {
52+
if package.name.is_none() && package.registry.is_none() {
53+
let version = package.version.to_string();
54+
version.trim_start_matches('^').serialize(serializer)
55+
} else {
56+
#[derive(Serialize)]
57+
struct Entry<'a> {
58+
package: Option<&'a PackageRef>,
59+
version: &'a str,
60+
registry: Option<&'a str>,
61+
}
62+
63+
Entry {
64+
package: package.name.as_ref(),
65+
version: package.version.to_string().trim_start_matches('^'),
66+
registry: package.registry.as_deref(),
67+
}
68+
.serialize(serializer)
69+
}
70+
}
71+
Self::Local(path) => {
72+
#[derive(Serialize)]
73+
struct Entry<'a> {
74+
path: &'a PathBuf,
75+
}
76+
77+
Entry { path }.serialize(serializer)
78+
}
79+
}
80+
}
81+
}
82+
83+
impl<'de> Deserialize<'de> for Dependency {
84+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
85+
where
86+
D: serde::Deserializer<'de>,
87+
{
88+
struct Visitor;
89+
90+
impl<'de> de::Visitor<'de> for Visitor {
91+
type Value = Dependency;
92+
93+
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
94+
write!(formatter, "a string or a table")
95+
}
96+
97+
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
98+
where
99+
E: de::Error,
100+
{
101+
Ok(Self::Value::Package(s.parse().map_err(de::Error::custom)?))
102+
}
103+
104+
fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
105+
where
106+
A: de::MapAccess<'de>,
107+
{
108+
#[derive(Default, Deserialize)]
109+
#[serde(default, deny_unknown_fields)]
110+
struct Entry {
111+
path: Option<PathBuf>,
112+
package: Option<PackageRef>,
113+
version: Option<VersionReq>,
114+
registry: Option<String>,
115+
}
116+
117+
let entry = Entry::deserialize(MapAccessDeserializer::new(map))?;
118+
119+
match (entry.path, entry.package, entry.version, entry.registry) {
120+
(Some(path), None, None, None) => Ok(Self::Value::Local(path)),
121+
(None, name, Some(version), registry) => {
122+
Ok(Self::Value::Package(RegistryPackage {
123+
name,
124+
version,
125+
registry,
126+
}))
127+
}
128+
(Some(_), None, Some(_), _) => Err(de::Error::custom(
129+
"cannot specify both `path` and `version` fields in a dependency entry",
130+
)),
131+
(Some(_), None, None, Some(_)) => Err(de::Error::custom(
132+
"cannot specify both `path` and `registry` fields in a dependency entry",
133+
)),
134+
(Some(_), Some(_), _, _) => Err(de::Error::custom(
135+
"cannot specify both `path` and `package` fields in a dependency entry",
136+
)),
137+
(None, None, _, _) => Err(de::Error::missing_field("package")),
138+
(None, Some(_), None, _) => Err(de::Error::missing_field("version")),
139+
}
140+
}
141+
}
142+
143+
deserializer.deserialize_any(Visitor)
144+
}
145+
}
146+
41147
impl FromStr for Dependency {
42148
type Err = anyhow::Error;
43149

@@ -363,8 +469,10 @@ impl<'a> DependencyResolver<'a> {
363469
&mut self,
364470
name: &PackageRef,
365471
dependency: &Dependency,
472+
is_wit: bool,
366473
) -> Result<()> {
367-
self.add_dependency_internal(name, dependency, false).await
474+
self.add_dependency_internal(name, dependency, false, is_wit)
475+
.await
368476
}
369477

370478
/// Add a dependency to the resolver. If the dependency already exists, then it will be
@@ -373,15 +481,18 @@ impl<'a> DependencyResolver<'a> {
373481
&mut self,
374482
name: &PackageRef,
375483
dependency: &Dependency,
484+
is_wit: bool,
376485
) -> Result<()> {
377-
self.add_dependency_internal(name, dependency, true).await
486+
self.add_dependency_internal(name, dependency, true, is_wit)
487+
.await
378488
}
379489

380490
async fn add_dependency_internal(
381491
&mut self,
382492
name: &PackageRef,
383493
dependency: &Dependency,
384494
force_override: bool,
495+
is_wit: bool,
385496
) -> Result<()> {
386497
match dependency {
387498
Dependency::Package(package) => {
@@ -434,13 +545,15 @@ impl<'a> DependencyResolver<'a> {
434545
return Ok(());
435546
}
436547

437-
// Now that we check we haven't already inserted this dep, get the packages from the
438-
// local dependency and add those to the resolver before adding the dependency
439-
let (_, packages) = get_packages(p)
440-
.context("Error getting dependent packages from local dependency")?;
441-
Box::pin(self.add_packages(packages))
442-
.await
443-
.context("Error adding packages to resolver for local dependency")?;
548+
// // Now that we check we haven't already inserted this dep, get the packages from the
549+
// // local dependency and add those to the resolver before adding the dependency
550+
if is_wit {
551+
let (_, packages) = get_packages(p)
552+
.context("Error getting dependent packages from local dependency")?;
553+
Box::pin(self.add_packages(packages))
554+
.await
555+
.context("Error adding packages to resolver for local dependency")?;
556+
}
444557

445558
let prev = self.resolutions.insert(name.clone(), res);
446559
assert!(prev.is_none());
@@ -454,16 +567,17 @@ impl<'a> DependencyResolver<'a> {
454567
/// requirements to the resolver
455568
pub async fn add_packages(
456569
&mut self,
457-
packages: impl IntoIterator<Item = (PackageRef, VersionReq)>,
570+
packages: impl IntoIterator<Item = (PackageRef, VersionReq, bool)>,
458571
) -> Result<()> {
459-
for (package, req) in packages {
572+
for (package, req, is_wit) in packages {
460573
self.add_dependency(
461574
&package,
462575
&Dependency::Package(RegistryPackage {
463576
name: Some(package.clone()),
464577
version: req,
465578
registry: None,
466579
}),
580+
is_wit,
467581
)
468582
.await?;
469583
}

crates/wasm-pkg-core/src/wit.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ pub async fn fetch_dependencies(
117117
/// for resolving dependencies.
118118
pub fn get_packages(
119119
path: impl AsRef<Path>,
120-
) -> Result<(PackageRef, HashSet<(PackageRef, VersionReq)>)> {
120+
) -> Result<(PackageRef, HashSet<(PackageRef, VersionReq, bool)>)> {
121121
let group =
122122
wit_parser::UnresolvedPackageGroup::parse_path(path).context("Couldn't parse package")?;
123123

@@ -137,7 +137,7 @@ pub fn get_packages(
137137
);
138138

139139
// Get all package refs from the main package and then from any nested packages
140-
let packages: HashSet<(PackageRef, VersionReq)> =
140+
let packages: HashSet<(PackageRef, VersionReq, bool)> =
141141
packages_from_foreign_deps(group.main.foreign_deps.into_keys())
142142
.chain(
143143
group
@@ -186,7 +186,7 @@ pub async fn resolve_dependencies(
186186
}
187187
};
188188
resolver
189-
.add_dependency(&pkg, &dep)
189+
.add_dependency(&pkg, &dep, true)
190190
.await
191191
.context("Unable to add dependency")?;
192192
}
@@ -289,7 +289,7 @@ pub async fn populate_dependencies(
289289

290290
fn packages_from_foreign_deps(
291291
deps: impl IntoIterator<Item = PackageName>,
292-
) -> impl Iterator<Item = (PackageRef, VersionReq)> {
292+
) -> impl Iterator<Item = (PackageRef, VersionReq, bool)> {
293293
deps.into_iter().filter_map(|dep| {
294294
let name = PackageRef::new(dep.namespace.parse().ok()?, dep.name.parse().ok()?);
295295
let version = match dep.version {
@@ -301,6 +301,7 @@ fn packages_from_foreign_deps(
301301
version
302302
.parse()
303303
.expect("Unable to parse into version request, this is programmer error"),
304+
true,
304305
))
305306
})
306307
}

0 commit comments

Comments
 (0)