Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 8 additions & 15 deletions crates/wasm-pkg-client/src/decoded_component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,18 @@ pub struct DecodedComponent {
}

impl DecodedComponent {
/// Decode a publishing source. `package_override`, when supplied, is the
/// authoritative `(package, version)`; otherwise the identity is extracted
/// from the binary.
pub async fn from_publishing_source(
data: PublishingSource,
package_override: Option<(PackageRef, Version)>,
) -> Result<(PublishingSource, DecodedComponent), Error> {
let (reader, decoded_wasm) = decode(SyncIoBridge::new(data)).await?;
let (package_ref, version) = extract_package_version(&decoded_wasm)?;
let (package_ref, version) = match package_override {
Some(id) => id,
None => extract_package_version(&decoded_wasm)?,
};

let mut data = reader.into_inner();
data.rewind().await?;
Expand All @@ -35,20 +42,6 @@ impl DecodedComponent {
))
}

/// Like [`Self::from_publishing_source`] but overrides the derived
/// `(package, version)` identity with `package_override` when supplied.
pub async fn from_publishing_source_with_package(
data: PublishingSource,
package_override: Option<(PackageRef, Version)>,
) -> Result<(PublishingSource, DecodedComponent), Error> {
let (data, mut decoded) = Self::from_publishing_source(data).await?;
if let Some((p, v)) = package_override {
decoded.package_ref = p;
decoded.version = v;
}
Ok((data, decoded))
}

/// Construct from a registry content stream. Callers already know the
/// `(package, version)` identity from the registry listing they followed
/// to get here, so we take it as input rather than re-deriving it from
Expand Down
2 changes: 1 addition & 1 deletion crates/wasm-pkg-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ impl Client {

// construct verifiable publishing source
let (data, candidate) =
DecodedComponent::from_publishing_source_with_package(data, pkg_authority).await?;
DecodedComponent::from_publishing_source(data, pkg_authority).await?;

let (package, version) = (
candidate.package().to_owned(),
Expand Down
75 changes: 75 additions & 0 deletions crates/wasm-pkg-client/tests/publish_package_override.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use std::{io::Cursor, path::Path};
use tempfile::TempDir;
use wasm_pkg_client::{Client, Config, PublishOpts};

const WIT: &str = r#"
package example:embedded@0.1.0;

world the-world {
export base: func() -> u32;
}
"#;

fn make_client(root: &Path) -> Client {
let toml = format!(
r#"
default_registry = "local"

[registry."local"]
type = "local"

[registry."local".local]
root = '{}'
"#,
root.display(),
);
let config = Config::from_toml(&toml).expect("local-backend config should parse");
Client::new(config)
}

fn component_bytes() -> Vec<u8> {
let mut resolve = wit_parser::Resolve::new();
let pkg = resolve
.push_str("test.wit", WIT)
.expect("test WIT should parse");
let world = resolve
.select_world(&[pkg], None)
.expect("test WIT should have exactly one world");
let mut module =
wit_component::dummy_module(&resolve, world, wit_parser::ManglingAndAbi::Standard32);
wit_component::embed_component_metadata(
&mut module,
&resolve,
world,
wit_component::StringEncoding::UTF8,
)
.expect("component metadata should embed");
wit_component::ComponentEncoder::default()
.module(&module)
.expect("dummy module should be accepted")
.validate(true)
.encode()
.expect("dummy module should encode as a component")
}

#[tokio::test]
async fn override_supplies_identity_for_component() {
let tmp = TempDir::new().unwrap();
let client = make_client(tmp.path());

let opts = PublishOpts {
package: Some(("example:app".parse().unwrap(), "1.0.0".parse().unwrap())),
..Default::default()
};
let (package, version) = client
.publish_release_data(Box::pin(Cursor::new(component_bytes())), opts)
.await
.expect("publishing a component with an explicit identity should succeed");

assert_eq!(package, "example:app".parse().unwrap());
assert_eq!(version, "1.0.0".parse().unwrap());
client
.get_release(&package, &version)
.await
.expect("published release should be retrievable at the supplied coordinate");
}