Skip to content
Open
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
5 changes: 5 additions & 0 deletions crates/wasm-pkg-core/src/lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ impl PartialEq for LockFile {
self.packages == other.packages && self.version == other.version
}
}
impl PartialEq<(u64, BTreeSet<LockedPackage>)> for LockFile {
fn eq(&self, other: &(u64, BTreeSet<LockedPackage>)) -> bool {
self.packages == other.1 && self.version == other.0
}
}

impl Eq for LockFile {}

Expand Down
42 changes: 39 additions & 3 deletions crates/wkg/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use wasm_pkg_common::{
package::PackageSpec,
registry::Registry,
};
use wasm_pkg_core::lock::LockFile;
use wit_component::DecodedWasm;

mod oci;
Expand Down Expand Up @@ -227,8 +228,9 @@ struct GetArgs {

#[derive(Args, Debug)]
struct PublishArgs {
/// The file to publish
file: PathBuf,
/// The file or directory to publish.
/// If a directory is provided, the package is built to a tempfile before publishing.
path: PathBuf,

#[command(flatten)]
registry_args: RegistryArgs,
Expand Down Expand Up @@ -260,10 +262,44 @@ impl PublishArgs {
} else {
None
};

// If the input is a directory, build a WIT package from it into a temp
// file first. _tmp is held until the publish completes so the file
// isn't deleted out from under us.
let (publish_path, _tmp) = if self.path.is_dir() {
let mut lock_file = LockFile::load(false).await?;
let prev_lock_ref = (lock_file.version, lock_file.packages.clone());
let (build_ref, _, bytes) =
wit::build_wit_dir(&self.path, client.clone(), &mut lock_file).await?;
// There is no way to check if we are in a git repository unlike `cargo publish --allow-dirty` so
// check against previous values.
if lock_file != prev_lock_ref {
return Err(anyhow::anyhow!(
"wkg.lock would be updated during publish, aborting"
))
.context("Run `wkg wit fetch` before attempting to publish");
}

let tmp = tempfile::Builder::new()
.prefix(&build_ref.to_string())
.suffix(".wasm")
.tempfile()
.context("Failed to create temporary file for built WIT package")?;
tokio::fs::write(tmp.path(), &bytes)
.await
.context("Failed to write built WIT package to temp file")?;
let tmp_pkg_path = tmp.path().to_path_buf();
tracing::debug!(tmp_pkg_path = %tmp_pkg_path.display(), "Wrote temporary WIT package file");

(tmp_pkg_path, Some(tmp))
} else {
(self.path.clone(), None)
};

let (package, version) = client
.client()?
.publish_release_file(
&self.file,
&publish_path,
PublishOpts {
package,
registry: self.registry_args.registry,
Expand Down
26 changes: 21 additions & 5 deletions crates/wkg/src/wit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use std::path::{Path, PathBuf};

use anyhow::Context;
use clap::{Args, Subcommand};
use wasm_pkg_client::caching::{CachingClient, FileCache};
use wasm_pkg_common::package::{PackageRef, Version};
use wasm_pkg_core::{
lock::LockFile,
wit::{self, OutputType},
Expand Down Expand Up @@ -86,12 +88,9 @@ pub struct UpdateArgs {

impl BuildArgs {
pub async fn run(self) -> anyhow::Result<()> {
check_dir(&self.dir).await?;
let client = self.common.get_client().await?;
let wkg_config = wasm_pkg_core::config::Config::load().await?;
let mut lock_file = LockFile::load(false).await?;
let (pkg_ref, version, bytes) =
wit::build_package(&wkg_config, self.dir, &mut lock_file, client).await?;
let (pkg_ref, version, bytes) = build_wit_dir(&self.dir, client, &mut lock_file).await?;
let output_path = if let Some(path) = self.output {
path
} else {
Expand All @@ -111,6 +110,19 @@ impl BuildArgs {
}
}

/// Build a WIT package from a directory, returning the resolved package ref, optional
/// version, and the encoded component bytes.
pub async fn build_wit_dir(
dir: impl AsRef<Path>,
client: CachingClient<FileCache>,
mut lock_file: &mut LockFile,
) -> anyhow::Result<(PackageRef, Option<Version>, Vec<u8>)> {
check_dir(&dir).await?;
let wkg_config = wasm_pkg_core::config::Config::load().await?;
let result = wit::build_package(&wkg_config, dir, lock_file, client).await?;
Ok(result)
}

impl FetchArgs {
pub async fn run(self) -> anyhow::Result<()> {
check_dir(&self.dir).await?;
Expand Down Expand Up @@ -154,5 +166,9 @@ impl UpdateArgs {
}

async fn check_dir(dir: impl AsRef<Path>) -> anyhow::Result<()> {
tokio::fs::metadata(dir).await.context("Unable to read wit directory. This command should be run from the parent directory of the wit directory or a directory can be overridden with the --wit-dir argument").map(|_|())
let dir = dir.as_ref();
tokio::fs::metadata(dir).await
.with_context(|| format!("unable to read wit directory: {}", dir.display()))
.context("This command should be run from the parent directory of the wit directory or a directory can be overridden with the --wit-dir argument")
.map(|_|())
}
Loading