Skip to content

Commit b1db797

Browse files
committed
added overlay setyp
1 parent 1968b61 commit b1db797

6 files changed

Lines changed: 115 additions & 25 deletions

File tree

crates/wasm-pkg-client/src/caching/file.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::{ContentStream, Release};
1616

1717
use super::Cache;
1818

19+
#[derive(Clone)]
1920
pub struct FileCache {
2021
root: PathBuf,
2122
}

crates/wasm-pkg-client/src/caching/mod.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ use std::sync::Arc;
44
use wasm_pkg_common::{
55
digest::ContentDigest,
66
package::{PackageRef, Version},
7+
registry::Registry,
78
Error,
89
};
910

10-
use crate::{Client, ContentStream, Release, VersionInfo};
11+
use crate::{Client, ContentStream, InnerClient, Release, VersionInfo};
1112

1213
mod file;
1314

@@ -45,20 +46,12 @@ pub trait Cache {
4546

4647
/// A client that caches response data using the given cache implementation. Can be used without an
4748
/// underlying client to be used as a read-only cache.
49+
#[derive(Clone)]
4850
pub struct CachingClient<T> {
4951
pub client: Option<Client>,
5052
cache: Arc<T>,
5153
}
5254

53-
impl<T: Cache> Clone for CachingClient<T> {
54-
fn clone(&self) -> Self {
55-
Self {
56-
client: self.client.clone(),
57-
cache: self.cache.clone(),
58-
}
59-
}
60-
}
61-
6255
impl<T: Cache> CachingClient<T> {
6356
/// Creates a new caching client from the given client and cache implementation. If no client is
6457
/// given, the client will be in offline or read-only mode, meaning it will only be able to return
@@ -70,6 +63,16 @@ impl<T: Cache> CachingClient<T> {
7063
}
7164
}
7265

66+
async fn with_overlays(
67+
mut self,
68+
overlays: impl IntoIterator<Item = (Registry, Arc<InnerClient>)>,
69+
) -> Self {
70+
if let Some(client) = &mut self.client {
71+
client.overlays = overlays.into_iter().collect();
72+
}
73+
self
74+
}
75+
7376
/// Returns whether or not the client is in read-only mode.
7477
pub fn is_readonly(&self) -> bool {
7578
self.client.is_none()

crates/wasm-pkg-client/src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ pub struct PublishOpts {
9595
pub struct Client {
9696
config: Arc<Config>,
9797
sources: Arc<RwLock<RegistrySources>>,
98+
/// Mapping of sources to local registries that will be overlaid on them.
99+
overlays: RegistrySources,
98100
}
99101

100102
impl Client {
@@ -103,6 +105,20 @@ impl Client {
103105
Self {
104106
config: Arc::new(config),
105107
sources: Default::default(),
108+
overlays: Default::default(),
109+
}
110+
}
111+
112+
/// Like [`Self::new`] but includes sources from source
113+
/// replacement configurations.
114+
pub fn new_with_overlays(
115+
config: Config,
116+
overlays: impl IntoIterator<Item = (Registry, Arc<InnerClient>)>,
117+
) -> Self {
118+
Self {
119+
config: Arc::new(config),
120+
sources: Default::default(),
121+
overlays: overlays.into_iter().collect(),
106122
}
107123
}
108124

crates/wasm-pkg-common/src/config.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,16 @@ pub struct RegistryConfig {
290290
}
291291

292292
impl RegistryConfig {
293+
pub fn with_default_backend<T: Serialize>(
294+
mut self,
295+
default_backend: &str,
296+
backend_config: T,
297+
) -> Result<Self, Error> {
298+
self.default_backend = Some(default_backend.to_string());
299+
self.set_backend_config("local", backend_config)?;
300+
Ok(self)
301+
}
302+
293303
/// Merges the given other config into this one.
294304
pub fn merge(&mut self, other: Self) {
295305
let Self {

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

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,59 @@ impl PublishPlan {
944944
}
945945
}
946946

947+
#[cfg(test)]
948+
mod tests {
949+
use std::collections::HashSet;
950+
use std::path::PathBuf;
951+
952+
use super::PublishPlan;
953+
use wasm_pkg_client::PackageRef;
954+
955+
fn transitive_local_paths() -> Vec<PathBuf> {
956+
let fixtures =
957+
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/transitive-local");
958+
["example-a", "example-b", "example-c"]
959+
.into_iter()
960+
.map(|name| fixtures.join(name).join("wit"))
961+
.collect()
962+
}
963+
964+
#[test]
965+
fn publish_plan_from_paths_collects_all_packages() {
966+
let paths = transitive_local_paths();
967+
let plan = PublishPlan::from_paths(&paths).expect("plan should build");
968+
969+
assert!(!plan.is_empty());
970+
assert_eq!(plan.len(), 3);
971+
972+
for name in ["example-a:foo", "example-b:bar", "example-c:baz"] {
973+
let pkg: PackageRef = name.parse().expect("valid package ref");
974+
assert!(
975+
plan.get_path(&pkg).is_some(),
976+
"expected `{name}` to have an associated path in the plan",
977+
);
978+
}
979+
}
980+
981+
#[test]
982+
fn publish_plan_iter_yields_each_package_once() {
983+
let paths = transitive_local_paths();
984+
let plan = PublishPlan::from_paths(&paths).expect("plan should build");
985+
986+
let seen: Vec<PackageRef> = plan.iter().map(|spec| spec.package.clone()).collect();
987+
assert_eq!(seen.len(), 3, "iter should yield one entry per package");
988+
989+
let unique: HashSet<_> = seen.iter().cloned().collect();
990+
assert_eq!(unique.len(), seen.len(), "iter must not yield duplicates");
991+
992+
let expected: HashSet<PackageRef> = ["example-a:foo", "example-b:bar", "example-c:baz"]
993+
.into_iter()
994+
.map(|s| s.parse().unwrap())
995+
.collect();
996+
assert_eq!(unique, expected);
997+
}
998+
}
999+
9471000
/// Format a collection of packages as a list
9481001
///
9491002
/// e.g. "foo:a@0.1.0, bar:b@0.2.0, and baz:c@0.3.0".

crates/wkg/src/main.rs

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use tokio::io::AsyncWriteExt;
77
use tracing::level_filters::LevelFilter;
88
use wasm_pkg_client::{
99
caching::{CachingClient, FileCache},
10+
local::LocalConfig,
1011
Client, PackagePublisher, PublishOpts,
1112
};
1213
use wasm_pkg_common::{
@@ -252,8 +253,6 @@ struct PublishArgs {
252253

253254
impl PublishArgs {
254255
pub async fn run(self) -> anyhow::Result<()> {
255-
let mut client = self.common.get_client().await?;
256-
257256
let package = match self.package {
258257
Some(_) if self.paths.len() > 2 => {
259258
anyhow::bail!("`--package` is currently unsupported when providing more than one path argument");
@@ -271,35 +270,41 @@ impl PublishArgs {
271270
let path = match &self.paths[..] {
272271
[path] => path,
273272
paths => {
274-
let (overlay, tmp_dir) = wasm_pkg_client::local::LocalBackend::temp_dir()?;
275-
let local_backend = wasm_pkg_client::local::LocalConfig {
276-
root: tmp_dir.path().to_path_buf(),
277-
};
278-
let mut reg_config = RegistryConfig::default();
279-
reg_config.set_default_backend(Some("local".to_owned()));
280-
reg_config.set_backend_config("local", &local_backend)?;
281-
282-
let plan = PublishPlan::from_paths(paths)?;
283-
let mut lock_file = LockFile::load(true).await?;
273+
let mut config = self.common.load_config().await?;
274+
let cache = self.common.load_cache().await?;
284275

276+
let (overlay, tmp_dir) = wasm_pkg_client::local::LocalBackend::temp_dir()?;
277+
let reg_config = RegistryConfig::default().with_default_backend(
278+
"local",
279+
LocalConfig {
280+
root: tmp_dir.path().to_path_buf(),
281+
},
282+
)?;
285283
// Route every package in the plan to the local overlay registry
286284
// backed by `reg_config`, so the client used in `build_wit_dir`
287285
// resolves these packages against the local overlay instead of
288286
// an upstream remote.
289-
let mut config = self.common.load_config().await?;
290-
let local_registry: Registry = "local".parse()?;
287+
let local_registry: Registry = "tmp_local_publish".parse()?;
291288
config
292289
.get_or_insert_registry_config_mut(&local_registry)
293290
.merge(reg_config);
291+
292+
let plan = PublishPlan::from_paths(paths)?;
293+
294+
// TODO(mkatychev): Add support for `PackageLoader::get_release` to handle
295+
// querying on a per package, namespace, and registry level
296+
// to handle cargo style overlays.
297+
// see this reference of `cargo::core::Dependency` usage for local overlays in Cargo:
298+
// https://github.com/rust-lang/cargo/blob/d6900d00af2644ea1c0068c5694d9dbe11a3ab39/src/cargo/sources/overlay.rs#L47
294299
for spec in plan.iter() {
295300
config.set_package_registry_override(
296301
spec.package.clone(),
297302
RegistryMapping::Registry(local_registry.clone()),
298303
);
299304
}
300-
let cache = self.common.load_cache().await?;
301305
let client = CachingClient::new(Some(Client::new(config)), cache);
302306

307+
let mut lock_file = LockFile::load(true).await?;
303308
for spec in plan.iter_edges() {
304309
let path = plan.get_path(&spec.package).unwrap();
305310
let (publish_path, _tmp) = if path.is_dir() {
@@ -333,6 +338,8 @@ impl PublishArgs {
333338
}
334339
};
335340

341+
let client = self.common.get_client().await?;
342+
336343
// If the input is a directory, build a WIT package from it into a temp
337344
// file first. _tmp is held until the publish completes so the file
338345
// isn't deleted out from under us.

0 commit comments

Comments
 (0)