From d6d91c495676d9d69532d2266441b5e3c796b441 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 30 Jun 2026 16:43:53 -0500 Subject: [PATCH 01/16] refactor(cli): move `wkg wit ` subcommands to `wkg `, add depracation warning to existing `wkg wit` commands --- crates/wkg/src/main.rs | 13 +++++++++++-- crates/wkg/src/wit.rs | 22 +++++++++++----------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/crates/wkg/src/main.rs b/crates/wkg/src/main.rs index de72833..e75474c 100644 --- a/crates/wkg/src/main.rs +++ b/crates/wkg/src/main.rs @@ -28,7 +28,7 @@ mod oci; mod wit; use oci::OciCommands; -use wit::WitCommands; +use wit::{BuildArgs, FetchArgs, UpdateArgs, WitCommands}; use crate::wit::temp_wit_file; @@ -105,6 +105,9 @@ enum Commands { /// Commands for interacting with OCI registries #[clap(subcommand)] Oci(OciCommands), + Build(BuildArgs), + Fetch(FetchArgs), + Update(UpdateArgs), /// Commands for interacting with WIT files and dependencies #[clap(subcommand)] Wit(WitCommands), @@ -615,6 +618,12 @@ async fn main() -> anyhow::Result<()> { Commands::Get(args) => args.run().await, Commands::Publish(args) => args.run().await, Commands::Oci(args) => args.run().await, - Commands::Wit(args) => args.run().await, + Commands::Build(args) => args.run().await, + Commands::Fetch(args) => args.run().await, + Commands::Update(args) => args.run().await, + Commands::Wit(args) => { + eprintln!("warning: `wkg wit ` is deprecated; use `wkg ` instead"); + args.run().await + } } } diff --git a/crates/wkg/src/wit.rs b/crates/wkg/src/wit.rs index 18d5d37..8c90c4d 100644 --- a/crates/wkg/src/wit.rs +++ b/crates/wkg/src/wit.rs @@ -16,19 +16,8 @@ use crate::Common; /// Commands for interacting with wit #[derive(Debug, Subcommand)] pub enum WitCommands { - /// Build a WIT package from a directory. By default, this will fetch all dependencies needed - /// and encode them in the WIT package. This will generate a lock file that can be used to fetch - /// the dependencies in the future. Build(BuildArgs), - /// Fetch dependencies for a component. This will read the package containing the world(s) you - /// have defined in the given wit directory (`wit` by default). It will then fetch the - /// dependencies and write them to the `deps` directory along with a lock file. If no lock file - /// exists, it will fetch all dependencies. If a lock file exists, it will fetch any - /// dependencies that are not in the lock file and update the lock file. To update the lock - /// file, use the `update` command. Fetch(FetchArgs), - /// Update the lock file with the latest dependencies. This will update all dependencies and - /// generate a new lock file. Update(UpdateArgs), } @@ -42,6 +31,9 @@ impl WitCommands { } } +/// Build a WIT package from a directory. By default, this will fetch all dependencies needed +/// and encode them in the WIT package. This will generate a lock file that can be used to fetch +/// the dependencies in the future. #[derive(Debug, Args)] pub struct BuildArgs { /// The directory containing the WIT files to build. @@ -57,6 +49,12 @@ pub struct BuildArgs { pub common: Common, } +/// Fetch dependencies for a component. This will read the package containing the world(s) you +/// have defined in the given wit directory (`wit` by default). It will then fetch the +/// dependencies and write them to the `deps` directory along with a lock file. If no lock file +/// exists, it will fetch all dependencies. If a lock file exists, it will fetch any +/// dependencies that are not in the lock file and update the lock file. To update the lock +/// file, use the `update` command. #[derive(Debug, Args)] pub struct FetchArgs { /// The directory containing the WIT files to fetch dependencies for. @@ -72,6 +70,8 @@ pub struct FetchArgs { pub common: Common, } +/// Update the lock file with the latest dependencies. This will update all dependencies and +/// generate a new lock file. #[derive(Debug, Args)] pub struct UpdateArgs { /// The directory containing the WIT files to update dependencies for. From b05575577cdfcb9901f7b90ae17e2bb32d1bcc78 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 30 Jun 2026 16:54:22 -0500 Subject: [PATCH 02/16] feat(cli): add support for `--color` flag --- Cargo.lock | 41 +++++++++++++++++++++++++++++++++++++++-- crates/wkg/Cargo.toml | 3 +++ crates/wkg/src/main.rs | 9 ++++++++- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9d3578c..4d31305 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,6 +55,21 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse 0.2.7", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + [[package]] name = "anstream" version = "1.0.0" @@ -62,7 +77,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", - "anstyle-parse", + "anstyle-parse 1.0.0", "anstyle-query", "anstyle-wincon", "colorchoice", @@ -76,6 +91,15 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + [[package]] name = "anstyle-parse" version = "1.0.0" @@ -690,7 +714,7 @@ version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ - "anstream", + "anstream 1.0.0", "anstyle", "clap_lex", "strsim", @@ -730,6 +754,16 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" +[[package]] +name = "colorchoice-clap" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb349f1be51d537c77d89ba5d1ba4344385175446eb01dacde8e1eace4094226" +dependencies = [ + "clap", + "colorchoice", +] + [[package]] name = "combine" version = "4.6.7" @@ -5738,9 +5772,12 @@ dependencies = [ name = "wkg" version = "0.16.0" dependencies = [ + "anstream 0.6.21", + "anstyle", "anyhow", "base64 0.22.1", "clap", + "colorchoice-clap", "docker_credential", "futures-util", "oci-client", diff --git a/crates/wkg/Cargo.toml b/crates/wkg/Cargo.toml index 908004c..8f6aa9b 100644 --- a/crates/wkg/Cargo.toml +++ b/crates/wkg/Cargo.toml @@ -14,8 +14,11 @@ default = ["docker-tests"] docker-tests = [] [dependencies] +anstream = "0.6" +anstyle = "1.0" anyhow = { workspace = true } clap = { version = "4.5", features = ["derive", "wrap_help", "env"] } +colorchoice-clap = "1.0" docker_credential = { workspace = true } futures-util = { workspace = true, features = ["io"] } oci-client = { workspace = true } diff --git a/crates/wkg/src/main.rs b/crates/wkg/src/main.rs index e75474c..4463d87 100644 --- a/crates/wkg/src/main.rs +++ b/crates/wkg/src/main.rs @@ -35,6 +35,9 @@ use crate::wit::temp_wit_file; #[derive(Parser, Debug)] #[command(version)] struct Cli { + #[command(flatten)] + color: colorchoice_clap::Color, + #[command(subcommand)] command: Commands, } @@ -612,6 +615,7 @@ async fn main() -> anyhow::Result<()> { .init(); let cli = Cli::parse(); + cli.color.write_global(); match cli.command { Commands::Config(args) => args.run().await, @@ -622,7 +626,10 @@ async fn main() -> anyhow::Result<()> { Commands::Fetch(args) => args.run().await, Commands::Update(args) => args.run().await, Commands::Wit(args) => { - eprintln!("warning: `wkg wit ` is deprecated; use `wkg ` instead"); + let yellow = anstyle::AnsiColor::Yellow.on_default(); + anstream::eprintln!( + "{yellow}warning: `wkg wit ` is deprecated; use `wkg ` instead{yellow:#}" + ); args.run().await } } From 3b0997619532947c38372ae3c08a778adf12b6f5 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 30 Jun 2026 17:23:04 -0500 Subject: [PATCH 03/16] feat(cli): add warnln! and statusln! macros to wkg --- crates/wkg/src/main.rs | 43 ++++++++++++++++++++++++++++++------------ crates/wkg/src/wit.rs | 1 + 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/crates/wkg/src/main.rs b/crates/wkg/src/main.rs index 4463d87..cbf9cb4 100644 --- a/crates/wkg/src/main.rs +++ b/crates/wkg/src/main.rs @@ -4,6 +4,7 @@ use std::{ path::PathBuf, }; +use anstream::eprintln; use anyhow::{anyhow, ensure, Context}; use clap::{Args, Parser, Subcommand, ValueEnum}; use futures_util::TryStreamExt; @@ -27,6 +28,26 @@ use wit_component::DecodedWasm; mod oci; mod wit; +#[macro_export] +macro_rules! warnln { + ($($arg:tt)*) => {{ + let style = ::anstyle::AnsiColor::Yellow.on_default() | ::anstyle::Effects::BOLD; + ::anstream::eprintln!("{style}warning{style:#}: {}", format_args!($($arg)*)); + }}; +} + +#[macro_export] +macro_rules! statusln { + ($label:expr, $($arg:tt)*) => {{ + let style = ::anstyle::AnsiColor::Green.on_default() | ::anstyle::Effects::BOLD; + ::anstream::eprintln!( + "{style}{:>12}{style:#} {}", + $label, + format_args!($($arg)*), + ); + }}; +} + use oci::OciCommands; use wit::{BuildArgs, FetchArgs, UpdateArgs, WitCommands}; @@ -197,7 +218,7 @@ impl ConfigArgs { if let Some(registry) = config.default_registry() { eprintln!("Default registry: {}", registry); } else { - eprintln!("Default registry is not set"); + warnln!("Default registry is not set"); } Ok(()) @@ -361,7 +382,7 @@ impl PublishArgs { .publish_release_data(source, publish_opts.clone()) .await?; if self.dry_run { - eprintln!("Aborting publish due to dry run: {}@{}", package, version); + warnln!("Aborting publish due to dry run: {}@{}", package, version); } else { eprintln!("Published {}@{}", package, version); } @@ -462,7 +483,8 @@ impl GetArgs { let version = match version { Some(ver) => ver, None => { - eprintln!("No version specified; fetching version list..."); + warnln!("no version specified; fetching version list..."); + statusln!("Fetching", "version list"); let versions = client.list_all_versions(&package).await?; tracing::trace!(?versions, "Fetched version list"); versions @@ -473,7 +495,7 @@ impl GetArgs { } }; - eprintln!("Getting {package}@{version}..."); + statusln!("Fetching", "{package}@{version}..."); let release = client .get_release(&package, &version) .await @@ -525,8 +547,8 @@ impl GetArgs { "wasm" => Format::Wasm, "wit" => Format::Wit, _ => { - eprintln!( - "Couldn't infer output format from file name {:?}", + warnln!( + "couldn't infer output format from file name {:?}", self.output.file_name().unwrap_or_default() ); Format::Auto @@ -548,11 +570,11 @@ impl GetArgs { } Ok(_) => None, Err(err) => { - tracing::debug!(?err, "failed to decode WIT package"); + warnln!("unable to decode WIT package"); if format == Format::Wit { return Err(err); } - eprintln!("Failed to detect package content type: {err:#}"); + eprintln!("failed to detect package content type: {err:#}"); None } } @@ -626,10 +648,7 @@ async fn main() -> anyhow::Result<()> { Commands::Fetch(args) => args.run().await, Commands::Update(args) => args.run().await, Commands::Wit(args) => { - let yellow = anstyle::AnsiColor::Yellow.on_default(); - anstream::eprintln!( - "{yellow}warning: `wkg wit ` is deprecated; use `wkg ` instead{yellow:#}" - ); + warnln!("`wkg wit ` is deprecated; use `wkg ` instead"); args.run().await } } diff --git a/crates/wkg/src/wit.rs b/crates/wkg/src/wit.rs index 8c90c4d..c30dde8 100644 --- a/crates/wkg/src/wit.rs +++ b/crates/wkg/src/wit.rs @@ -1,6 +1,7 @@ //! Args and commands for interacting with WIT files and dependencies use std::path::{Path, PathBuf}; +use anstream::eprintln; use anyhow::Context; use clap::{Args, Subcommand}; use tempfile::NamedTempFile; From 6b578f26e262bf266f247f9612aa81689668fa70 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 30 Jun 2026 18:00:28 -0500 Subject: [PATCH 04/16] feat(cli): add helpln! to wkg --- crates/wkg/src/main.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/crates/wkg/src/main.rs b/crates/wkg/src/main.rs index cbf9cb4..a008cf6 100644 --- a/crates/wkg/src/main.rs +++ b/crates/wkg/src/main.rs @@ -28,6 +28,11 @@ use wit_component::DecodedWasm; mod oci; mod wit; +use oci::OciCommands; +use wit::{BuildArgs, FetchArgs, UpdateArgs, WitCommands}; + +use crate::wit::temp_wit_file; + #[macro_export] macro_rules! warnln { ($($arg:tt)*) => {{ @@ -39,7 +44,7 @@ macro_rules! warnln { #[macro_export] macro_rules! statusln { ($label:expr, $($arg:tt)*) => {{ - let style = ::anstyle::AnsiColor::Green.on_default() | ::anstyle::Effects::BOLD; + let style = ::anstyle::AnsiColor::Cyan.on_default() | ::anstyle::Effects::BOLD; ::anstream::eprintln!( "{style}{:>12}{style:#} {}", $label, @@ -48,10 +53,13 @@ macro_rules! statusln { }}; } -use oci::OciCommands; -use wit::{BuildArgs, FetchArgs, UpdateArgs, WitCommands}; - -use crate::wit::temp_wit_file; +#[macro_export] +macro_rules! helpln { + ($($arg:tt)*) => {{ + let style = ::anstyle::AnsiColor::Magenta.on_default() | ::anstyle::Effects::BOLD; + ::anstream::eprintln!("{style}{:>7}{style:#}: {}", "help", format_args!($($arg)*)); + }}; +} #[derive(Parser, Debug)] #[command(version)] @@ -648,7 +656,8 @@ async fn main() -> anyhow::Result<()> { Commands::Fetch(args) => args.run().await, Commands::Update(args) => args.run().await, Commands::Wit(args) => { - warnln!("`wkg wit ` is deprecated; use `wkg ` instead"); + warnln!("`wkg wit ` is deprecated"); + helpln!("use `wkg ` instead"); args.run().await } } From 3572fe56e7bc371de3a9e7994b63ad560958bc0d Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 30 Jun 2026 18:38:58 -0500 Subject: [PATCH 05/16] feat(core): add ansi styling in Display of PackageRef and PackageSpec --- Cargo.lock | 1 + crates/wasm-pkg-common/Cargo.toml | 1 + crates/wasm-pkg-common/src/package.rs | 28 ++++++++++++++++++++++----- crates/wasm-pkg-core/src/resolver.rs | 17 ++++++++++++---- crates/wkg/src/main.rs | 2 +- 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4d31305..6c075ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5203,6 +5203,7 @@ dependencies = [ name = "wasm-pkg-common" version = "0.16.0" dependencies = [ + "anstyle", "anyhow", "bytes", "etcetera 0.11.0", diff --git a/crates/wasm-pkg-common/Cargo.toml b/crates/wasm-pkg-common/Cargo.toml index 104515a..f501add 100644 --- a/crates/wasm-pkg-common/Cargo.toml +++ b/crates/wasm-pkg-common/Cargo.toml @@ -18,6 +18,7 @@ registry-config = [ oci_extras = [] [dependencies] +anstyle = "1.0" anyhow = { workspace = true } bytes = { workspace = true } etcetera = { workspace = true, optional = true } diff --git a/crates/wasm-pkg-common/src/package.rs b/crates/wasm-pkg-common/src/package.rs index 00a816e..d299474 100644 --- a/crates/wasm-pkg-common/src/package.rs +++ b/crates/wasm-pkg-common/src/package.rs @@ -1,11 +1,16 @@ use std::str::FromStr; +use anstyle::{Ansi256Color, AnsiColor, Style}; use serde::{Deserialize, Serialize}; use crate::{label::Label, Error}; pub use semver::Version; +const LABEL: Style = AnsiColor::BrightBlue.on_default().bold(); +const VERSION: Style = AnsiColor::BrightRed.on_default(); +const SEP: Style = Ansi256Color(249).on_default(); + /// A package reference, consisting of kebab-case namespace and name. /// /// Ex: `wasm-pkg:client` @@ -35,7 +40,15 @@ impl PackageRef { impl std::fmt::Display for PackageRef { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}:{}", self.namespace, self.name) + if f.alternate() { + write!( + f, + "{LABEL}{}{LABEL:#}{SEP}:{SEP:#}{LABEL}{}{LABEL:#}", + self.namespace, self.name, + ) + } else { + write!(f, "{}:{}", self.namespace, self.name) + } } } @@ -70,10 +83,15 @@ impl FromStr for PackageRef { } impl std::fmt::Display for PackageSpec { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if let Some(version) = &self.version { - write!(f, "{}@{}", self.package, version) - } else { - write!(f, "{}", self.package) + match (&self.version, f.alternate()) { + (Some(version), true) => write!( + f, + "{:#}{SEP}@{SEP:#}{VERSION}{version}{VERSION:#}", + self.package, + ), + (Some(version), false) => write!(f, "{}@{version}", self.package), + (None, true) => write!(f, "{:#}", self.package), + (None, false) => write!(f, "{}", self.package), } } } diff --git a/crates/wasm-pkg-core/src/resolver.rs b/crates/wasm-pkg-core/src/resolver.rs index af6f2f2..06b1a79 100644 --- a/crates/wasm-pkg-core/src/resolver.rs +++ b/crates/wasm-pkg-core/src/resolver.rs @@ -945,7 +945,7 @@ impl PublishPlan { impl std::fmt::Display for PublishPlan { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - // TODO(mkatychev): handle with anstyle and anstream, passing in `anstream::AutoStream` for colour choice + let alt = f.alternate(); for id in self.dependents.nodes_iter() { let dep = &self.dependents[id]; // initial dependency graph visualization @@ -955,8 +955,13 @@ impl std::fmt::Display for PublishPlan { .peekable(); if neighbors.peek().is_none() { - // tracing::debug!("{dep} has no dependents"); - writeln!(f, "[{dep} has no dependents]")?; + if alt { + writeln!(f, "[{dep:#} has no dependents]")?; + } else { + writeln!(f, "[{dep} has no dependents]")?; + } + } else if alt { + writeln!(f, "[{dep:#}]")?; } else { writeln!(f, "[{dep}]")?; } @@ -969,7 +974,11 @@ impl std::fmt::Display for PublishPlan { "╰─" }; - writeln!(f, "{separator}─▶ {pkg}")?; + if alt { + writeln!(f, "{separator}─▶ {pkg:#}")?; + } else { + writeln!(f, "{separator}─▶ {pkg}")?; + } } } Ok(()) diff --git a/crates/wkg/src/main.rs b/crates/wkg/src/main.rs index a008cf6..d90a8d1 100644 --- a/crates/wkg/src/main.rs +++ b/crates/wkg/src/main.rs @@ -312,7 +312,7 @@ impl PublishArgs { .merge(reg_config); let mut plan = PublishPlan::from_paths(paths)?; - eprintln!("{plan}"); + anstream::eprintln!("{plan:#}"); // TODO(mkatychev): Add support for `PackageLoader::get_release` to handle // querying on a per package, namespace, and registry level From ff425f3ec5ae078ad255b2c97927ad1655195859 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 1 Jul 2026 13:11:50 -0500 Subject: [PATCH 06/16] refactor(core): feature gate anstyle --- crates/wasm-pkg-common/Cargo.toml | 3 +- crates/wasm-pkg-common/src/package.rs | 52 +++++++++++++++++---------- crates/wasm-pkg-core/src/resolver.rs | 16 ++------- crates/wkg/Cargo.toml | 2 +- crates/wkg/src/main.rs | 2 +- 5 files changed, 40 insertions(+), 35 deletions(-) diff --git a/crates/wasm-pkg-common/Cargo.toml b/crates/wasm-pkg-common/Cargo.toml index f501add..327832b 100644 --- a/crates/wasm-pkg-common/Cargo.toml +++ b/crates/wasm-pkg-common/Cargo.toml @@ -18,7 +18,8 @@ registry-config = [ oci_extras = [] [dependencies] -anstyle = "1.0" +# Enables ANSI `Display` formatting for select types +anstyle = { version = "1.0", optional = true } anyhow = { workspace = true } bytes = { workspace = true } etcetera = { workspace = true, optional = true } diff --git a/crates/wasm-pkg-common/src/package.rs b/crates/wasm-pkg-common/src/package.rs index d299474..d3bbac4 100644 --- a/crates/wasm-pkg-common/src/package.rs +++ b/crates/wasm-pkg-common/src/package.rs @@ -1,15 +1,24 @@ use std::str::FromStr; -use anstyle::{Ansi256Color, AnsiColor, Style}; use serde::{Deserialize, Serialize}; use crate::{label::Label, Error}; pub use semver::Version; -const LABEL: Style = AnsiColor::BrightBlue.on_default().bold(); -const VERSION: Style = AnsiColor::BrightRed.on_default(); -const SEP: Style = Ansi256Color(249).on_default(); +#[cfg(feature = "anstyle")] +mod ansi { + use anstyle::{Ansi256Color, AnsiColor, Style}; + + pub const LABEL: Style = AnsiColor::BrightBlue.on_default().bold(); + pub const VERSION: Style = AnsiColor::BrightRed.on_default(); + pub const SEP: Style = Ansi256Color(249).on_default(); + + pub fn is_terminal() -> bool { + use std::io::IsTerminal; + std::io::stderr().is_terminal() + } +} /// A package reference, consisting of kebab-case namespace and name. /// @@ -40,15 +49,16 @@ impl PackageRef { impl std::fmt::Display for PackageRef { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if f.alternate() { - write!( + #[cfg(feature = "anstyle")] + if ansi::is_terminal() { + use ansi::{LABEL, SEP}; + return write!( f, "{LABEL}{}{LABEL:#}{SEP}:{SEP:#}{LABEL}{}{LABEL:#}", self.namespace, self.name, - ) - } else { - write!(f, "{}:{}", self.namespace, self.name) + ); } + write!(f, "{}:{}", self.namespace, self.name) } } @@ -83,15 +93,21 @@ impl FromStr for PackageRef { } impl std::fmt::Display for PackageSpec { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match (&self.version, f.alternate()) { - (Some(version), true) => write!( - f, - "{:#}{SEP}@{SEP:#}{VERSION}{version}{VERSION:#}", - self.package, - ), - (Some(version), false) => write!(f, "{}@{version}", self.package), - (None, true) => write!(f, "{:#}", self.package), - (None, false) => write!(f, "{}", self.package), + #[cfg(feature = "anstyle")] + if ansi::is_terminal() { + use ansi::{SEP, VERSION}; + return match &self.version { + Some(version) => write!( + f, + "{}{SEP}@{SEP:#}{VERSION}{version}{VERSION:#}", + self.package, + ), + None => write!(f, "{}", self.package), + }; + } + match &self.version { + Some(version) => write!(f, "{}@{version}", self.package), + None => write!(f, "{}", self.package), } } } diff --git a/crates/wasm-pkg-core/src/resolver.rs b/crates/wasm-pkg-core/src/resolver.rs index 06b1a79..3f25449 100644 --- a/crates/wasm-pkg-core/src/resolver.rs +++ b/crates/wasm-pkg-core/src/resolver.rs @@ -945,23 +945,15 @@ impl PublishPlan { impl std::fmt::Display for PublishPlan { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let alt = f.alternate(); for id in self.dependents.nodes_iter() { let dep = &self.dependents[id]; - // initial dependency graph visualization let mut neighbors = self .dependents .neighbors_directed(id, Direction::Outgoing) .peekable(); if neighbors.peek().is_none() { - if alt { - writeln!(f, "[{dep:#} has no dependents]")?; - } else { - writeln!(f, "[{dep} has no dependents]")?; - } - } else if alt { - writeln!(f, "[{dep:#}]")?; + writeln!(f, "[{dep} has no dependents]")?; } else { writeln!(f, "[{dep}]")?; } @@ -974,11 +966,7 @@ impl std::fmt::Display for PublishPlan { "╰─" }; - if alt { - writeln!(f, "{separator}─▶ {pkg:#}")?; - } else { - writeln!(f, "{separator}─▶ {pkg}")?; - } + writeln!(f, "{separator}─▶ {pkg}")?; } } Ok(()) diff --git a/crates/wkg/Cargo.toml b/crates/wkg/Cargo.toml index 8f6aa9b..2f848f5 100644 --- a/crates/wkg/Cargo.toml +++ b/crates/wkg/Cargo.toml @@ -27,7 +27,7 @@ tempfile = { workspace = true } tokio = { workspace = true, features = ["macros", "rt"] } tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["ansi"] } -wasm-pkg-common = { workspace = true } +wasm-pkg-common = { workspace = true, features = ["anstyle"] } wasm-pkg-client = { workspace = true } wit-component = { workspace = true } wasm-pkg-core = { workspace = true } diff --git a/crates/wkg/src/main.rs b/crates/wkg/src/main.rs index d90a8d1..e46726a 100644 --- a/crates/wkg/src/main.rs +++ b/crates/wkg/src/main.rs @@ -312,7 +312,7 @@ impl PublishArgs { .merge(reg_config); let mut plan = PublishPlan::from_paths(paths)?; - anstream::eprintln!("{plan:#}"); + anstream::eprintln!("{plan}"); // TODO(mkatychev): Add support for `PackageLoader::get_release` to handle // querying on a per package, namespace, and registry level From 85696544143a547bc962392c0b332285ce7adc8c Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 1 Jul 2026 13:21:36 -0500 Subject: [PATCH 07/16] refactor(cli): use core and common with anstyle feature flag --- crates/wasm-pkg-core/Cargo.toml | 3 +++ crates/wkg/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/wasm-pkg-core/Cargo.toml b/crates/wasm-pkg-core/Cargo.toml index 1e8818b..4411680 100644 --- a/crates/wasm-pkg-core/Cargo.toml +++ b/crates/wasm-pkg-core/Cargo.toml @@ -7,6 +7,9 @@ version.workspace = true authors.workspace = true license.workspace = true +[features] +anstyle = ["wasm-pkg-common/anstyle"] + [dependencies] anyhow = { workspace = true } futures-util = { workspace = true } diff --git a/crates/wkg/Cargo.toml b/crates/wkg/Cargo.toml index 2f848f5..db6650a 100644 --- a/crates/wkg/Cargo.toml +++ b/crates/wkg/Cargo.toml @@ -30,7 +30,7 @@ tracing-subscriber = { workspace = true, features = ["ansi"] } wasm-pkg-common = { workspace = true, features = ["anstyle"] } wasm-pkg-client = { workspace = true } wit-component = { workspace = true } -wasm-pkg-core = { workspace = true } +wasm-pkg-core = { workspace = true, features = ["anstyle"] } [dev-dependencies] base64 = { workspace = true } From 82379d58a01ab8582a4861513465020b30c6d4ab Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 1 Jul 2026 13:32:45 -0500 Subject: [PATCH 08/16] chore(config): run cargo-autoinherit --- Cargo.lock | 25 +++++++++++++------------ Cargo.toml | 15 +++++++++++++++ crates/wasm-pkg-client/Cargo.toml | 22 ++++++++-------------- crates/wasm-pkg-common/Cargo.toml | 5 ++--- crates/wasm-pkg-core/Cargo.toml | 6 +++--- crates/wkg/Cargo.toml | 8 ++++---- 6 files changed, 45 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6c075ce..4ed24e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -386,9 +386,9 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "aws-lc-rs" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" +checksum = "4342d8937fc7e5dd9b1c60292261c0670c882a2cd1719cfc11b1af41731e32ad" dependencies = [ "aws-lc-sys", "zeroize", @@ -396,14 +396,15 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.41.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" +checksum = "6d9ceb1da931507a12f4fccea479dccd00da1943e1b4ae72d8e502d707361444" dependencies = [ "cc", "cmake", "dunce", "fs_extra", + "pkg-config", ] [[package]] @@ -2292,9 +2293,9 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" dependencies = [ "libc", ] @@ -3663,9 +3664,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" dependencies = [ "web-time", "zeroize", @@ -4358,9 +4359,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.51" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c17d80feb7334b40c484e45ed1a5273dfd8bfda537c3be2e74a06a6686f327" +checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50" dependencies = [ "deranged", "num-conv", @@ -4378,9 +4379,9 @@ checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-macros" -version = "0.2.30" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcef1a61bdb119096e153208ec5cbec23944ce8bca13be5c7f60c634f7403935" +checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f" dependencies = [ "num-conv", "time-core", diff --git a/Cargo.toml b/Cargo.toml index 03eef6f..be18439 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,21 @@ wasm-pkg-core = { version = "0.16.0", path = "crates/wasm-pkg-core" } wasm-metadata = "0.244" wit-component = "0.244" wit-parser = "0.244" +anstream = "0.6" +anstyle = "1.0" +async-trait = "0.1.77" +clap = "4.5" +colorchoice-clap = "1.0" +glob = "0.3.3" +http = "1.1.0" +indexmap = "2.5" +reqwest = { version = "0.12.0", default-features = false } +rstest = "0.23" +secrecy = "0.8" +url = "2.5.0" +warg-client = "0.9.2" +warg-crypto = "0.9.2" +warg-protocol = "0.9.2" # https://github.com/crate-ci/typos/blob/master/docs/reference.md [workspace.metadata.typos.default] diff --git a/crates/wasm-pkg-client/Cargo.toml b/crates/wasm-pkg-client/Cargo.toml index d10fc69..004e039 100644 --- a/crates/wasm-pkg-client/Cargo.toml +++ b/crates/wasm-pkg-client/Cargo.toml @@ -15,7 +15,7 @@ docker-tests = [] [dependencies] anyhow = { workspace = true } -async-trait = "0.1.77" +async-trait = { workspace = true } base64 = { workspace = true } bytes = { workspace = true } docker_credential = { workspace = true } @@ -23,14 +23,8 @@ etcetera = { workspace = true } futures-util = { workspace = true, features = ["io"] } oci-client = { workspace = true } oci-wasm = { workspace = true } -reqwest = { version = "0.12.0", default-features = false, features = [ - "charset", - "http2", - "json", - "macos-system-configuration", - "rustls-tls", -] } -secrecy = { version = "0.8", features = ["serde"] } +reqwest = { workspace = true, features = ["charset", "http2", "json", "macos-system-configuration", "rustls-tls"] } +secrecy = { workspace = true, features = ["serde"] } serde = { workspace = true } serde_json = { workspace = true } sha2 = { workspace = true } @@ -40,14 +34,14 @@ tokio-util = { workspace = true, features = ["io", "io-util", "codec"] } toml = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true } -url = "2.5.0" -warg-client = "0.9.2" -warg-crypto = "0.9.2" +url = { workspace = true } +warg-client = { workspace = true } +warg-crypto = { workspace = true } wasm-metadata = { workspace = true } -warg-protocol = "0.9.2" +warg-protocol = { workspace = true } wasm-pkg-common = { workspace = true, features = ["registry-config"] } wit-component = { workspace = true } -petgraph = "0.8.3" +petgraph = { workspace = true } tempfile = { workspace = true } [dev-dependencies] diff --git a/crates/wasm-pkg-common/Cargo.toml b/crates/wasm-pkg-common/Cargo.toml index 327832b..ef9b922 100644 --- a/crates/wasm-pkg-common/Cargo.toml +++ b/crates/wasm-pkg-common/Cargo.toml @@ -18,13 +18,12 @@ registry-config = [ oci_extras = [] [dependencies] -# Enables ANSI `Display` formatting for select types -anstyle = { version = "1.0", optional = true } +anstyle = { workspace = true, optional = true } anyhow = { workspace = true } bytes = { workspace = true } etcetera = { workspace = true, optional = true } futures-util = { workspace = true } -http = "1.1.0" +http = { workspace = true } semver = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } diff --git a/crates/wasm-pkg-core/Cargo.toml b/crates/wasm-pkg-core/Cargo.toml index 4411680..da57b43 100644 --- a/crates/wasm-pkg-core/Cargo.toml +++ b/crates/wasm-pkg-core/Cargo.toml @@ -13,7 +13,7 @@ anstyle = ["wasm-pkg-common/anstyle"] [dependencies] anyhow = { workspace = true } futures-util = { workspace = true } -indexmap = "2.5" +indexmap = { workspace = true } semver = { workspace = true } serde = { workspace = true } tokio = { workspace = true, features = ["macros", "rt"] } @@ -45,5 +45,5 @@ features = [ [dev-dependencies] tempfile = { workspace = true } sha2 = { workspace = true } -rstest = "0.23" -glob = "0.3.3" +rstest = { workspace = true } +glob = { workspace = true } diff --git a/crates/wkg/Cargo.toml b/crates/wkg/Cargo.toml index db6650a..691d7f7 100644 --- a/crates/wkg/Cargo.toml +++ b/crates/wkg/Cargo.toml @@ -14,11 +14,11 @@ default = ["docker-tests"] docker-tests = [] [dependencies] -anstream = "0.6" -anstyle = "1.0" +anstream = { workspace = true } +anstyle = { workspace = true } anyhow = { workspace = true } -clap = { version = "4.5", features = ["derive", "wrap_help", "env"] } -colorchoice-clap = "1.0" +clap = { workspace = true, features = ["derive", "wrap_help", "env"] } +colorchoice-clap = { workspace = true } docker_credential = { workspace = true } futures-util = { workspace = true, features = ["io"] } oci-client = { workspace = true } From d620cc7dc4817733336974587cc0d4523c0b7114 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 1 Jul 2026 13:35:15 -0500 Subject: [PATCH 09/16] style(config): sort workspace dependencies --- Cargo.toml | 48 +++++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index be18439..02d0ca3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,20 +9,31 @@ authors = ["The Wasmtime Project Developers"] license = "Apache-2.0 WITH LLVM-exception" [workspace.dependencies] +wasm-pkg-client = { version = "0.16.0", path = "crates/wasm-pkg-client" } +wasm-pkg-common = { version = "0.16.0", path = "crates/wasm-pkg-common" } +wasm-pkg-core = { version = "0.16.0", path = "crates/wasm-pkg-core" } + +anstream = "0.6" +anstyle = "1.0" anyhow = "1" +async-trait = "0.1.77" base64 = "0.22" bytes = "1.11" +clap = "4.5" +colorchoice-clap = "1.0" docker_credential = "1.3.2" etcetera = "0.11" futures-util = "0.3.30" -oci-client = { version = "0.16", default-features = false, features = [ - "rustls-tls", -] } -oci-wasm = { version = "0.4", default-features = false, features = [ - "rustls-tls", -] } +glob = "0.3.3" +http = "1.1.0" +indexmap = "2.5" +oci-client = { version = "0.16", default-features = false, features = [ "rustls-tls" ] } +oci-wasm = { version = "0.4", default-features = false, features = [ "rustls-tls" ] } petgraph = "0.8.3" rcgen = "0.14.8" +reqwest = { version = "0.12.0", default-features = false } +rstest = "0.23" +secrecy = "0.8" semver = "1.0.23" serde = { version = "1.0", features = ["derive"] } serde_json = "1" @@ -34,31 +45,14 @@ tokio = "1.44.2" tokio-util = "0.7.10" toml = "0.8" tracing = "0.1.40" -tracing-subscriber = { version = "0.3.20", default-features = false, features = [ - "fmt", - "env-filter", -] } -wasm-pkg-common = { version = "0.16.0", path = "crates/wasm-pkg-common" } -wasm-pkg-client = { version = "0.16.0", path = "crates/wasm-pkg-client" } -wasm-pkg-core = { version = "0.16.0", path = "crates/wasm-pkg-core" } -wasm-metadata = "0.244" -wit-component = "0.244" -wit-parser = "0.244" -anstream = "0.6" -anstyle = "1.0" -async-trait = "0.1.77" -clap = "4.5" -colorchoice-clap = "1.0" -glob = "0.3.3" -http = "1.1.0" -indexmap = "2.5" -reqwest = { version = "0.12.0", default-features = false } -rstest = "0.23" -secrecy = "0.8" +tracing-subscriber = { version = "0.3.20", default-features = false, features = [ "fmt", "env-filter" ] } url = "2.5.0" warg-client = "0.9.2" warg-crypto = "0.9.2" warg-protocol = "0.9.2" +wasm-metadata = "0.244" +wit-component = "0.244" +wit-parser = "0.244" # https://github.com/crate-ci/typos/blob/master/docs/reference.md [workspace.metadata.typos.default] From 865420924be037eb041450587713c6d399cdb9d4 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 1 Jul 2026 13:40:35 -0500 Subject: [PATCH 10/16] fix(vis): moved ansi mod items to pub(crate) --- crates/wasm-pkg-common/src/package.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/wasm-pkg-common/src/package.rs b/crates/wasm-pkg-common/src/package.rs index d3bbac4..2b69ed2 100644 --- a/crates/wasm-pkg-common/src/package.rs +++ b/crates/wasm-pkg-common/src/package.rs @@ -7,14 +7,14 @@ use crate::{label::Label, Error}; pub use semver::Version; #[cfg(feature = "anstyle")] -mod ansi { +pub(crate) mod ansi { use anstyle::{Ansi256Color, AnsiColor, Style}; - pub const LABEL: Style = AnsiColor::BrightBlue.on_default().bold(); - pub const VERSION: Style = AnsiColor::BrightRed.on_default(); - pub const SEP: Style = Ansi256Color(249).on_default(); + pub(crate) const LABEL: Style = AnsiColor::BrightBlue.on_default().bold(); + pub(crate) const VERSION: Style = AnsiColor::BrightRed.on_default(); + pub(crate) const SEP: Style = Ansi256Color(249).on_default(); - pub fn is_terminal() -> bool { + pub(crate) fn is_terminal() -> bool { use std::io::IsTerminal; std::io::stderr().is_terminal() } From 91c5d4f600f5ff0e82dd7a2e8f54e6ffba594714 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 1 Jul 2026 22:27:44 -0500 Subject: [PATCH 11/16] refactor(core,common): rename "anstyle" feature flag to "ansi-term-output" --- crates/wasm-pkg-common/Cargo.toml | 1 + crates/wasm-pkg-common/src/package.rs | 6 +++--- crates/wasm-pkg-core/Cargo.toml | 2 +- crates/wkg/Cargo.toml | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/crates/wasm-pkg-common/Cargo.toml b/crates/wasm-pkg-common/Cargo.toml index ef9b922..78e6746 100644 --- a/crates/wasm-pkg-common/Cargo.toml +++ b/crates/wasm-pkg-common/Cargo.toml @@ -14,6 +14,7 @@ registry-config = [ "dep:tokio", "dep:toml", ] +ansi-term-output = [ "dep:anstyle" ] # Extra features to facilitate making working with OCI images easier oci_extras = [] diff --git a/crates/wasm-pkg-common/src/package.rs b/crates/wasm-pkg-common/src/package.rs index 2b69ed2..3532567 100644 --- a/crates/wasm-pkg-common/src/package.rs +++ b/crates/wasm-pkg-common/src/package.rs @@ -6,7 +6,7 @@ use crate::{label::Label, Error}; pub use semver::Version; -#[cfg(feature = "anstyle")] +#[cfg(feature = "ansi-term-output")] pub(crate) mod ansi { use anstyle::{Ansi256Color, AnsiColor, Style}; @@ -49,7 +49,7 @@ impl PackageRef { impl std::fmt::Display for PackageRef { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - #[cfg(feature = "anstyle")] + #[cfg(feature = "ansi-term-output")] if ansi::is_terminal() { use ansi::{LABEL, SEP}; return write!( @@ -93,7 +93,7 @@ impl FromStr for PackageRef { } impl std::fmt::Display for PackageSpec { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - #[cfg(feature = "anstyle")] + #[cfg(feature = "ansi-term-output")] if ansi::is_terminal() { use ansi::{SEP, VERSION}; return match &self.version { diff --git a/crates/wasm-pkg-core/Cargo.toml b/crates/wasm-pkg-core/Cargo.toml index da57b43..ab9fd0a 100644 --- a/crates/wasm-pkg-core/Cargo.toml +++ b/crates/wasm-pkg-core/Cargo.toml @@ -8,7 +8,7 @@ authors.workspace = true license.workspace = true [features] -anstyle = ["wasm-pkg-common/anstyle"] +ansi-term-output = ["wasm-pkg-common/ansi-term-output"] [dependencies] anyhow = { workspace = true } diff --git a/crates/wkg/Cargo.toml b/crates/wkg/Cargo.toml index 691d7f7..e6a9d80 100644 --- a/crates/wkg/Cargo.toml +++ b/crates/wkg/Cargo.toml @@ -27,10 +27,10 @@ tempfile = { workspace = true } tokio = { workspace = true, features = ["macros", "rt"] } tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["ansi"] } -wasm-pkg-common = { workspace = true, features = ["anstyle"] } +wasm-pkg-common = { workspace = true, features = ["ansi-term-output"] } wasm-pkg-client = { workspace = true } wit-component = { workspace = true } -wasm-pkg-core = { workspace = true, features = ["anstyle"] } +wasm-pkg-core = { workspace = true, features = ["ansi-term-output"] } [dev-dependencies] base64 = { workspace = true } From cbc3feacc695077a05dee01123a13bb656f0f0fa Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 1 Jul 2026 22:35:35 -0500 Subject: [PATCH 12/16] refactor(common): remove uses of is_terminal --- crates/wasm-pkg-common/src/package.rs | 34 ++++++++++++--------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/crates/wasm-pkg-common/src/package.rs b/crates/wasm-pkg-common/src/package.rs index 3532567..af7b030 100644 --- a/crates/wasm-pkg-common/src/package.rs +++ b/crates/wasm-pkg-common/src/package.rs @@ -13,11 +13,6 @@ pub(crate) mod ansi { pub(crate) const LABEL: Style = AnsiColor::BrightBlue.on_default().bold(); pub(crate) const VERSION: Style = AnsiColor::BrightRed.on_default(); pub(crate) const SEP: Style = Ansi256Color(249).on_default(); - - pub(crate) fn is_terminal() -> bool { - use std::io::IsTerminal; - std::io::stderr().is_terminal() - } } /// A package reference, consisting of kebab-case namespace and name. @@ -50,7 +45,7 @@ impl PackageRef { impl std::fmt::Display for PackageRef { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { #[cfg(feature = "ansi-term-output")] - if ansi::is_terminal() { + { use ansi::{LABEL, SEP}; return write!( f, @@ -58,6 +53,7 @@ impl std::fmt::Display for PackageRef { self.namespace, self.name, ); } + #[cfg(not(feature = "ansi-term-output"))] write!(f, "{}:{}", self.namespace, self.name) } } @@ -93,20 +89,20 @@ impl FromStr for PackageRef { } impl std::fmt::Display for PackageSpec { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - #[cfg(feature = "ansi-term-output")] - if ansi::is_terminal() { - use ansi::{SEP, VERSION}; - return match &self.version { - Some(version) => write!( - f, - "{}{SEP}@{SEP:#}{VERSION}{version}{VERSION:#}", - self.package, - ), - None => write!(f, "{}", self.package), - }; - } match &self.version { - Some(version) => write!(f, "{}@{version}", self.package), + Some(version) => { + #[cfg(feature = "ansi-term-output")] + { + use ansi::{SEP, VERSION}; + return write!( + f, + "{}{SEP}@{SEP:#}{VERSION}{version}{VERSION:#}", + self.package, + ); + } + #[cfg(not(feature = "ansi-term-output"))] + write!(f, "{}@{version}", self.package) + } None => write!(f, "{}", self.package), } } From 4cdb5018d3dced1339a15257b70705a043de978b Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 1 Jul 2026 22:36:21 -0500 Subject: [PATCH 13/16] fmt --- crates/wasm-pkg-common/src/package.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/wasm-pkg-common/src/package.rs b/crates/wasm-pkg-common/src/package.rs index af7b030..6b60570 100644 --- a/crates/wasm-pkg-common/src/package.rs +++ b/crates/wasm-pkg-common/src/package.rs @@ -47,11 +47,11 @@ impl std::fmt::Display for PackageRef { #[cfg(feature = "ansi-term-output")] { use ansi::{LABEL, SEP}; - return write!( + write!( f, "{LABEL}{}{LABEL:#}{SEP}:{SEP:#}{LABEL}{}{LABEL:#}", self.namespace, self.name, - ); + ) } #[cfg(not(feature = "ansi-term-output"))] write!(f, "{}:{}", self.namespace, self.name) @@ -94,11 +94,11 @@ impl std::fmt::Display for PackageSpec { #[cfg(feature = "ansi-term-output")] { use ansi::{SEP, VERSION}; - return write!( + write!( f, "{}{SEP}@{SEP:#}{VERSION}{version}{VERSION:#}", self.package, - ); + ) } #[cfg(not(feature = "ansi-term-output"))] write!(f, "{}@{version}", self.package) From 0fe596d1a2a57cdafa01ca1945c6736983c95140 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Thu, 2 Jul 2026 00:09:11 -0500 Subject: [PATCH 14/16] refactor: update to rust 2024, add test feature flag --- Cargo.toml | 4 +-- crates/wasm-pkg-client/src/caching/file.rs | 2 +- crates/wasm-pkg-client/src/caching/mod.rs | 2 +- crates/wasm-pkg-client/src/lib.rs | 2 +- crates/wasm-pkg-client/src/loader.rs | 4 +-- crates/wasm-pkg-client/src/local.rs | 4 +-- crates/wasm-pkg-client/src/metadata.rs | 4 +-- crates/wasm-pkg-client/src/oci/config.rs | 4 +-- crates/wasm-pkg-client/src/oci/loader.rs | 8 ++--- crates/wasm-pkg-client/src/oci/mod.rs | 4 +-- crates/wasm-pkg-client/src/warg/config.rs | 2 +- crates/wasm-pkg-client/src/warg/loader.rs | 6 ++-- crates/wasm-pkg-client/src/warg/mod.rs | 6 ++-- crates/wasm-pkg-client/tests/e2e.rs | 4 +-- crates/wasm-pkg-common/Cargo.toml | 2 ++ crates/wasm-pkg-common/src/config.rs | 6 ++-- crates/wasm-pkg-common/src/digest.rs | 11 ++++--- crates/wasm-pkg-common/src/label.rs | 2 +- crates/wasm-pkg-common/src/metadata.rs | 2 +- crates/wasm-pkg-common/src/package.rs | 12 +++---- crates/wasm-pkg-core/Cargo.toml | 2 ++ crates/wasm-pkg-core/src/lock.rs | 18 +++++------ crates/wasm-pkg-core/src/resolver.rs | 37 +++++++++++++--------- crates/wasm-pkg-core/src/wit.rs | 4 +-- crates/wasm-pkg-core/tests/common.rs | 2 +- crates/wasm-pkg-core/tests/fetch.rs | 8 ++++- crates/wkg/Cargo.toml | 3 ++ crates/wkg/src/main.rs | 8 +++-- crates/wkg/src/oci.rs | 16 +++++++--- crates/wkg/tests/common.rs | 4 +-- crates/wkg/tests/e2e.rs | 4 +-- 31 files changed, 113 insertions(+), 84 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 02d0ca3..c90977c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,9 @@ [workspace] members = ["crates/*"] -resolver = "2" +resolver = "3" [workspace.package] -edition = "2021" +edition = "2024" version = "0.16.0" authors = ["The Wasmtime Project Developers"] license = "Apache-2.0 WITH LLVM-exception" diff --git a/crates/wasm-pkg-client/src/caching/file.rs b/crates/wasm-pkg-client/src/caching/file.rs index e54a1e8..385e3cb 100644 --- a/crates/wasm-pkg-client/src/caching/file.rs +++ b/crates/wasm-pkg-client/src/caching/file.rs @@ -7,9 +7,9 @@ use etcetera::BaseStrategy; use futures_util::{StreamExt, TryStreamExt}; use tokio_util::io::{ReaderStream, StreamReader}; use wasm_pkg_common::{ + Error, digest::ContentDigest, package::{PackageRef, Version}, - Error, }; use crate::{ContentStream, Release}; diff --git a/crates/wasm-pkg-client/src/caching/mod.rs b/crates/wasm-pkg-client/src/caching/mod.rs index e90a161..b1a2d23 100644 --- a/crates/wasm-pkg-client/src/caching/mod.rs +++ b/crates/wasm-pkg-client/src/caching/mod.rs @@ -2,9 +2,9 @@ use std::future::Future; use std::sync::Arc; use wasm_pkg_common::{ + Error, digest::ContentDigest, package::{PackageRef, Version}, - Error, }; use crate::{Client, ContentStream, Release, VersionInfo}; diff --git a/crates/wasm-pkg-client/src/lib.rs b/crates/wasm-pkg-client/src/lib.rs index 3d1c85c..f887b48 100644 --- a/crates/wasm-pkg-client/src/lib.rs +++ b/crates/wasm-pkg-client/src/lib.rs @@ -47,12 +47,12 @@ use tokio::sync::RwLock; use tokio_util::io::SyncIoBridge; use wasm_pkg_common::metadata::{LOCAL_PROTOCOL, OCI_PROTOCOL, WARG_PROTOCOL}; pub use wasm_pkg_common::{ + Error, config::{Config, CustomConfig, RegistryMapping}, digest::ContentDigest, metadata::RegistryMetadata, package::{PackageRef, Version}, registry::Registry, - Error, }; use wit_component::DecodedWasm; diff --git a/crates/wasm-pkg-client/src/loader.rs b/crates/wasm-pkg-client/src/loader.rs index 7189bd1..26fae09 100644 --- a/crates/wasm-pkg-client/src/loader.rs +++ b/crates/wasm-pkg-client/src/loader.rs @@ -1,13 +1,13 @@ use async_trait::async_trait; use futures_util::StreamExt; use wasm_pkg_common::{ - package::{PackageRef, Version}, Error, + package::{PackageRef, Version}, }; use crate::{ - release::{Release, VersionInfo}, ContentStream, + release::{Release, VersionInfo}, }; #[async_trait] diff --git a/crates/wasm-pkg-client/src/local.rs b/crates/wasm-pkg-client/src/local.rs index c4fc4d8..c9a11be 100644 --- a/crates/wasm-pkg-client/src/local.rs +++ b/crates/wasm-pkg-client/src/local.rs @@ -16,18 +16,18 @@ use sha2::{Digest, Sha256}; use tempfile::TempDir; use tokio_util::io::ReaderStream; use wasm_pkg_common::{ + Error, config::RegistryConfig, digest::ContentDigest, metadata::LOCAL_PROTOCOL, package::{PackageRef, Version}, - Error, }; use crate::{ + ContentStream, PublishingSource, loader::PackageLoader, publisher::PackagePublisher, release::{Release, VersionInfo}, - ContentStream, PublishingSource, }; #[derive(Clone, Debug, Deserialize, Serialize)] diff --git a/crates/wasm-pkg-client/src/metadata.rs b/crates/wasm-pkg-client/src/metadata.rs index d88d66d..efeeff3 100644 --- a/crates/wasm-pkg-client/src/metadata.rs +++ b/crates/wasm-pkg-client/src/metadata.rs @@ -1,9 +1,9 @@ use anyhow::Context; use reqwest::StatusCode; use wasm_pkg_common::{ - metadata::{RegistryMetadata, REGISTRY_METADATA_PATH}, - registry::Registry, Error, + metadata::{REGISTRY_METADATA_PATH, RegistryMetadata}, + registry::Registry, }; /// Extension trait for [`RegistryMetadata`] adding client functionality. diff --git a/crates/wasm-pkg-client/src/oci/config.rs b/crates/wasm-pkg-client/src/oci/config.rs index 37d8e9a..1f6c7a2 100644 --- a/crates/wasm-pkg-client/src/oci/config.rs +++ b/crates/wasm-pkg-client/src/oci/config.rs @@ -1,12 +1,12 @@ use anyhow::Context; use base64::{ - engine::{DecodePaddingMode, GeneralPurpose, GeneralPurposeConfig}, Engine, + engine::{DecodePaddingMode, GeneralPurpose, GeneralPurposeConfig}, }; use oci_client::client::{Certificate, CertificateEncoding, ClientConfig}; use secrecy::{ExposeSecret, SecretString}; use serde::{Deserialize, Serialize, Serializer}; -use wasm_pkg_common::{config::RegistryConfig, Error}; +use wasm_pkg_common::{Error, config::RegistryConfig}; /// Registry configuration for OCI backends. /// diff --git a/crates/wasm-pkg-client/src/oci/loader.rs b/crates/wasm-pkg-client/src/oci/loader.rs index 30dfc17..2e22cdc 100644 --- a/crates/wasm-pkg-client/src/oci/loader.rs +++ b/crates/wasm-pkg-client/src/oci/loader.rs @@ -1,16 +1,16 @@ use async_trait::async_trait; use futures_util::{StreamExt, TryStreamExt}; -use oci_client::{manifest::OciDescriptor, RegistryOperation}; +use oci_client::{RegistryOperation, manifest::OciDescriptor}; use warg_protocol::Version; -use wasm_pkg_common::{package::PackageRef, Error}; +use wasm_pkg_common::{Error, package::PackageRef}; use crate::{ + ContentStream, loader::PackageLoader, release::{Release, VersionInfo}, - ContentStream, }; -use super::{oci_registry_error, OciBackend}; +use super::{OciBackend, oci_registry_error}; #[async_trait] impl PackageLoader for OciBackend { diff --git a/crates/wasm-pkg-client/src/oci/mod.rs b/crates/wasm-pkg-client/src/oci/mod.rs index 71ef22c..344e8c0 100644 --- a/crates/wasm-pkg-client/src/oci/mod.rs +++ b/crates/wasm-pkg-client/src/oci/mod.rs @@ -10,17 +10,17 @@ mod publisher; use docker_credential::{CredentialRetrievalError, DockerCredential}; use oci_client::{ - errors::OciDistributionError, secrets::RegistryAuth, Reference, RegistryOperation, + Reference, RegistryOperation, errors::OciDistributionError, secrets::RegistryAuth, }; use secrecy::ExposeSecret; use serde::Deserialize; use tokio::sync::OnceCell; use wasm_pkg_common::{ + Error, config::RegistryConfig, metadata::RegistryMetadata, package::{PackageRef, Version}, registry::Registry, - Error, }; /// Re-exported for convenience. diff --git a/crates/wasm-pkg-client/src/warg/config.rs b/crates/wasm-pkg-client/src/warg/config.rs index 63636d1..e575c27 100644 --- a/crates/wasm-pkg-client/src/warg/config.rs +++ b/crates/wasm-pkg-client/src/warg/config.rs @@ -3,7 +3,7 @@ use std::{fmt::Debug, path::PathBuf, sync::Arc}; use secrecy::{ExposeSecret, SecretString}; use serde::{Deserialize, Serialize, Serializer}; use warg_crypto::signing::PrivateKey; -use wasm_pkg_common::{config::RegistryConfig, Error}; +use wasm_pkg_common::{Error, config::RegistryConfig}; /// Registry configuration for Warg backends. /// diff --git a/crates/wasm-pkg-client/src/warg/loader.rs b/crates/wasm-pkg-client/src/warg/loader.rs index b6f2ff2..1e27ca0 100644 --- a/crates/wasm-pkg-client/src/warg/loader.rs +++ b/crates/wasm-pkg-client/src/warg/loader.rs @@ -2,17 +2,17 @@ use anyhow::anyhow; use async_trait::async_trait; use futures_util::{StreamExt, TryStreamExt}; use wasm_pkg_common::{ - package::{PackageRef, Version}, Error, + package::{PackageRef, Version}, }; use crate::{ + ContentStream, loader::PackageLoader, release::{Release, VersionInfo}, - ContentStream, }; -use super::{package_ref_to_name, warg_registry_error, WargBackend}; +use super::{WargBackend, package_ref_to_name, warg_registry_error}; #[async_trait] impl PackageLoader for WargBackend { diff --git a/crates/wasm-pkg-client/src/warg/mod.rs b/crates/wasm-pkg-client/src/warg/mod.rs index c444868..900170e 100644 --- a/crates/wasm-pkg-client/src/warg/mod.rs +++ b/crates/wasm-pkg-client/src/warg/mod.rs @@ -3,12 +3,12 @@ use std::sync::Arc; use serde::Deserialize; -use warg_client::{storage::PackageInfo, ClientError, FileSystemClient}; +use warg_client::{ClientError, FileSystemClient, storage::PackageInfo}; use warg_crypto::signing::PrivateKey; use warg_protocol::registry::PackageName; use wasm_pkg_common::{ - config::RegistryConfig, metadata::RegistryMetadata, package::PackageRef, registry::Registry, - Error, + Error, config::RegistryConfig, metadata::RegistryMetadata, package::PackageRef, + registry::Registry, }; mod config; diff --git a/crates/wasm-pkg-client/tests/e2e.rs b/crates/wasm-pkg-client/tests/e2e.rs index aad96b8..7646cf3 100644 --- a/crates/wasm-pkg-client/tests/e2e.rs +++ b/crates/wasm-pkg-client/tests/e2e.rs @@ -7,9 +7,9 @@ const FIXTURE_WASM: &str = "./tests/testdata/binary_wit.wasm"; #[tokio::test] async fn publish_and_fetch_smoke_test() { use testcontainers::{ + GenericImage, ImageExt, core::{IntoContainerPort, WaitFor}, runners::AsyncRunner, - GenericImage, ImageExt, }; let _container = GenericImage::new("registry", "2") @@ -62,9 +62,9 @@ async fn publish_and_fetch_smoke_test() { #[tokio::test] async fn publish_and_fetch_succeed_with_self_signed_registry() { use testcontainers::{ + GenericImage, ImageExt, core::{IntoContainerPort, WaitFor}, runners::AsyncRunner, - GenericImage, ImageExt, }; let (fixture_pem_cert, fixture_pem_key) = generate_self_signed_tls_fixture(); diff --git a/crates/wasm-pkg-common/Cargo.toml b/crates/wasm-pkg-common/Cargo.toml index 78e6746..86f5fdd 100644 --- a/crates/wasm-pkg-common/Cargo.toml +++ b/crates/wasm-pkg-common/Cargo.toml @@ -15,6 +15,8 @@ registry-config = [ "dep:toml", ] ansi-term-output = [ "dep:anstyle" ] +# running `cargo test` (implicit `--workspace` flag), leaks `ansi-term-output` from wkg +test = [] # Extra features to facilitate making working with OCI images easier oci_extras = [] diff --git a/crates/wasm-pkg-common/src/config.rs b/crates/wasm-pkg-common/src/config.rs index 809d194..60cadc5 100644 --- a/crates/wasm-pkg-common/src/config.rs +++ b/crates/wasm-pkg-common/src/config.rs @@ -1,5 +1,5 @@ use std::{ - collections::{hash_map::Entry, HashMap}, + collections::{HashMap, hash_map::Entry}, io::ErrorKind, path::{Path, PathBuf}, }; @@ -7,11 +7,11 @@ use std::{ use serde::{Deserialize, Serialize}; use crate::{ + Error, label::Label, - metadata::{RegistryMetadata, LOCAL_PROTOCOL}, + metadata::{LOCAL_PROTOCOL, RegistryMetadata}, package::PackageRef, registry::Registry, - Error, }; mod toml; diff --git a/crates/wasm-pkg-common/src/digest.rs b/crates/wasm-pkg-common/src/digest.rs index dd19a09..34913d9 100644 --- a/crates/wasm-pkg-common/src/digest.rs +++ b/crates/wasm-pkg-common/src/digest.rs @@ -1,7 +1,7 @@ use std::str::FromStr; use bytes::Bytes; -use futures_util::{future::ready, stream::once, Stream, StreamExt, TryStream, TryStreamExt}; +use futures_util::{Stream, StreamExt, TryStream, TryStreamExt, future::ready, stream::once}; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; @@ -14,10 +14,13 @@ pub enum ContentDigest { } impl ContentDigest { - pub fn validating_stream( + pub fn validating_stream( &self, - stream: impl TryStream, - ) -> impl Stream> { + stream: S, + ) -> impl Stream> + use + where + S: TryStream, + { let want = self.clone(); stream.map_ok(Some).chain(once(async { Ok(None) })).scan( Sha256::new(), diff --git a/crates/wasm-pkg-common/src/label.rs b/crates/wasm-pkg-common/src/label.rs index 7aa733c..069175c 100644 --- a/crates/wasm-pkg-common/src/label.rs +++ b/crates/wasm-pkg-common/src/label.rs @@ -41,7 +41,7 @@ impl TryFrom for Label { match chars.next() { None => return Err(InvalidLabel::EmptyWord), Some(ch) if !ch.is_ascii_lowercase() => { - return Err(InvalidLabel::InvalidWordFirstChar) + return Err(InvalidLabel::InvalidWordFirstChar); } _ => (), } diff --git a/crates/wasm-pkg-common/src/metadata.rs b/crates/wasm-pkg-common/src/metadata.rs index dda8332..c2973cc 100644 --- a/crates/wasm-pkg-common/src/metadata.rs +++ b/crates/wasm-pkg-common/src/metadata.rs @@ -3,7 +3,7 @@ use std::{ collections::{BTreeSet, HashMap}, }; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde::{Deserialize, Serialize, de::DeserializeOwned}; use crate::Error; diff --git a/crates/wasm-pkg-common/src/package.rs b/crates/wasm-pkg-common/src/package.rs index 6b60570..8859dd9 100644 --- a/crates/wasm-pkg-common/src/package.rs +++ b/crates/wasm-pkg-common/src/package.rs @@ -2,11 +2,11 @@ use std::str::FromStr; use serde::{Deserialize, Serialize}; -use crate::{label::Label, Error}; +use crate::{Error, label::Label}; pub use semver::Version; -#[cfg(feature = "ansi-term-output")] +#[cfg(all(feature = "ansi-term-output", not(feature = "test")))] pub(crate) mod ansi { use anstyle::{Ansi256Color, AnsiColor, Style}; @@ -44,7 +44,7 @@ impl PackageRef { impl std::fmt::Display for PackageRef { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - #[cfg(feature = "ansi-term-output")] + #[cfg(all(feature = "ansi-term-output", not(feature = "test")))] { use ansi::{LABEL, SEP}; write!( @@ -53,7 +53,7 @@ impl std::fmt::Display for PackageRef { self.namespace, self.name, ) } - #[cfg(not(feature = "ansi-term-output"))] + #[cfg(not(all(feature = "ansi-term-output", not(feature = "test"))))] write!(f, "{}:{}", self.namespace, self.name) } } @@ -91,7 +91,7 @@ impl std::fmt::Display for PackageSpec { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match &self.version { Some(version) => { - #[cfg(feature = "ansi-term-output")] + #[cfg(all(feature = "ansi-term-output", not(feature = "test")))] { use ansi::{SEP, VERSION}; write!( @@ -100,7 +100,7 @@ impl std::fmt::Display for PackageSpec { self.package, ) } - #[cfg(not(feature = "ansi-term-output"))] + #[cfg(not(all(feature = "ansi-term-output", not(feature = "test"))))] write!(f, "{}@{version}", self.package) } None => write!(f, "{}", self.package), diff --git a/crates/wasm-pkg-core/Cargo.toml b/crates/wasm-pkg-core/Cargo.toml index ab9fd0a..f116de4 100644 --- a/crates/wasm-pkg-core/Cargo.toml +++ b/crates/wasm-pkg-core/Cargo.toml @@ -9,6 +9,8 @@ license.workspace = true [features] ansi-term-output = ["wasm-pkg-common/ansi-term-output"] +# running `cargo test` (implicit `--workspace` flag), leaks `ansi-term-output` from wkg +test = ["wasm-pkg-common/test"] [dependencies] anyhow = { workspace = true } diff --git a/crates/wasm-pkg-core/src/lock.rs b/crates/wasm-pkg-core/src/lock.rs index f27d5c5..2e2fad2 100644 --- a/crates/wasm-pkg-core/src/lock.rs +++ b/crates/wasm-pkg-core/src/lock.rs @@ -202,15 +202,13 @@ impl LockFile { name: package_ref.clone(), registry: registry.map(ToString::to_string), versions: vec![], - }) { - if let Some(locked) = pkg - .versions - .iter() - .find(|locked| &locked.requirement == requirement) - { - tracing::info!(%package_ref, ?registry, %requirement, resolved_version = %locked.version, "dependency package was resolved by the lock file"); - return Ok(Some(locked)); - } + }) && let Some(locked) = pkg + .versions + .iter() + .find(|locked| &locked.requirement == requirement) + { + tracing::info!(%package_ref, ?registry, %requirement, resolved_version = %locked.version, "dependency package was resolved by the lock file"); + return Ok(Some(locked)); } tracing::info!(%package_ref, ?registry, %requirement, "dependency package was not in the lock file"); @@ -685,7 +683,7 @@ mod sys { use windows_sys::Win32::Foundation::HANDLE; use windows_sys::Win32::Foundation::{ERROR_INVALID_FUNCTION, ERROR_LOCK_VIOLATION}; use windows_sys::Win32::Storage::FileSystem::{ - LockFileEx, UnlockFile, LOCKFILE_EXCLUSIVE_LOCK, LOCKFILE_FAIL_IMMEDIATELY, + LOCKFILE_EXCLUSIVE_LOCK, LOCKFILE_FAIL_IMMEDIATELY, LockFileEx, UnlockFile, }; pub(super) fn lock_shared(file: &File) -> Result<()> { diff --git a/crates/wasm-pkg-core/src/resolver.rs b/crates/wasm-pkg-core/src/resolver.rs index 77e6c47..1943c38 100644 --- a/crates/wasm-pkg-core/src/resolver.rs +++ b/crates/wasm-pkg-core/src/resolver.rs @@ -2,22 +2,22 @@ // NOTE(thomastaylor312): This is copied and adapted from the `cargo-component` crate: https://github.com/bytecodealliance/cargo-component/blob/f0be1c7d9917aa97e9102e69e3b838dae38d624b/crates/core/src/registry.rs use std::{ - collections::{hash_map, BTreeSet, HashMap, HashSet}, + collections::{BTreeSet, HashMap, HashSet, hash_map}, fmt::Debug, ops::{Deref, DerefMut}, path::{Path, PathBuf}, str::FromStr, }; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; use futures_util::TryStreamExt; use indexmap::{IndexMap, IndexSet}; -use petgraph::{acyclic::Acyclic, graph::NodeIndex, stable_graph::StableDiGraph, Direction}; +use petgraph::{Direction, acyclic::Acyclic, graph::NodeIndex, stable_graph::StableDiGraph}; use semver::{Comparator, Op, Version, VersionReq}; use tokio::io::{AsyncRead, AsyncReadExt}; use wasm_pkg_client::{ - caching::{CachingClient, FileCache}, Client, Config, ContentDigest, Error as WasmPkgError, PackageRef, Release, VersionInfo, + caching::{CachingClient, FileCache}, }; use wasm_pkg_common::package::PackageSpec; use wit_component::DecodedWasm; @@ -580,15 +580,15 @@ impl<'a> DependencyResolver<'a> { let release = client .get_release(&dependency.package, selected_version) .await?; - if let Some(digest) = digest { - if &release.content_digest != digest { - bail!( - "component registry package `{name}` (v`{version}`) has digest `{content}` but the lock file specifies digest `{digest}`", - name = dependency.package, - version = release.version, - content = release.content_digest, - ); - } + if let Some(digest) = digest + && &release.content_digest != digest + { + bail!( + "component registry package `{name}` (v`{version}`) has digest `{content}` but the lock file specifies digest `{digest}`", + name = dependency.package, + version = release.version, + content = release.content_digest, + ); } let resolution = RegistryResolution { name: name.clone(), @@ -803,7 +803,10 @@ fn visit<'a>( // the package is resolved if let Some(dep) = deps.get(name) { if !visiting.insert(name) { - anyhow::bail!("foreign dependency `{name}` forms a dependency cycle while parsing dependency `{other}`", other = resolution.name()); + anyhow::bail!( + "foreign dependency `{name}` forms a dependency cycle while parsing dependency `{other}`", + other = resolution.name() + ); } visit(dep, deps, order, visiting)?; @@ -825,7 +828,11 @@ fn visit<'a>( if let Some(dep) = deps.get(&package.name) { if !visiting.insert(&package.name) { - anyhow::bail!("foreign dependency `{name}` forms a dependency cycle while parsing dependency `{other}`", name = package.name, other = resolution.name()); + anyhow::bail!( + "foreign dependency `{name}` forms a dependency cycle while parsing dependency `{other}`", + name = package.name, + other = resolution.name() + ); } visit(dep, deps, order, visiting)?; diff --git a/crates/wasm-pkg-core/src/wit.rs b/crates/wasm-pkg-core/src/wit.rs index b8e9000..69332e1 100644 --- a/crates/wasm-pkg-core/src/wit.rs +++ b/crates/wasm-pkg-core/src/wit.rs @@ -7,12 +7,12 @@ use std::{ }; use anyhow::{Context, Result}; -use petgraph::{data::Build, Direction}; +use petgraph::{Direction, data::Build}; use semver::{Version, VersionReq}; use wasm_metadata::{AddMetadata, AddMetadataField}; use wasm_pkg_client::{ - caching::{CachingClient, FileCache}, PackageRef, + caching::{CachingClient, FileCache}, }; use wasm_pkg_common::package::PackageSpec; use wit_component::WitPrinter; diff --git a/crates/wasm-pkg-core/tests/common.rs b/crates/wasm-pkg-core/tests/common.rs index 6ff25b4..f1adcbf 100644 --- a/crates/wasm-pkg-core/tests/common.rs +++ b/crates/wasm-pkg-core/tests/common.rs @@ -2,8 +2,8 @@ use std::path::{Path, PathBuf}; use tempfile::TempDir; use wasm_pkg_client::{ - caching::{CachingClient, FileCache}, Client, + caching::{CachingClient, FileCache}, }; pub fn fixture_dir() -> PathBuf { diff --git a/crates/wasm-pkg-core/tests/fetch.rs b/crates/wasm-pkg-core/tests/fetch.rs index f563a4c..11f9d2f 100644 --- a/crates/wasm-pkg-core/tests/fetch.rs +++ b/crates/wasm-pkg-core/tests/fetch.rs @@ -165,5 +165,11 @@ async fn build_component(fixture_path: &Path) { .output() .await .expect("Should be able to execute build command"); - assert!(output.status.success(), "Should be able to build the component successfully. Exited with error code: {}\nStdout:\n\n{}\n\nStderr:\n\n{}", output.status.code().unwrap_or(-1), String::from_utf8_lossy(&output.stdout), String::from_utf8_lossy(&output.stderr)); + assert!( + output.status.success(), + "Should be able to build the component successfully. Exited with error code: {}\nStdout:\n\n{}\n\nStderr:\n\n{}", + output.status.code().unwrap_or(-1), + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); } diff --git a/crates/wkg/Cargo.toml b/crates/wkg/Cargo.toml index e6a9d80..1754df0 100644 --- a/crates/wkg/Cargo.toml +++ b/crates/wkg/Cargo.toml @@ -33,7 +33,10 @@ wit-component = { workspace = true } wasm-pkg-core = { workspace = true, features = ["ansi-term-output"] } [dev-dependencies] +wasm-pkg-core = { workspace = true, features = ["test"] } +wasm-pkg-common = { workspace = true, features = ["test"] } base64 = { workspace = true } serde_json = { workspace = true } tempfile = { workspace = true } testcontainers = { workspace = true } +anstream = { workspace = true, features = ["test"] } diff --git a/crates/wkg/src/main.rs b/crates/wkg/src/main.rs index e46726a..56f0286 100644 --- a/crates/wkg/src/main.rs +++ b/crates/wkg/src/main.rs @@ -5,15 +5,15 @@ use std::{ }; use anstream::eprintln; -use anyhow::{anyhow, ensure, Context}; +use anyhow::{Context, anyhow, ensure}; use clap::{Args, Parser, Subcommand, ValueEnum}; use futures_util::TryStreamExt; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tracing::level_filters::LevelFilter; use wasm_pkg_client::{ + Client, PublishOpts, caching::{CachingClient, FileCache}, local::LocalConfig, - Client, PublishOpts, }; use wasm_pkg_common::{ self, @@ -447,7 +447,9 @@ impl PublishArgs { fn publish_opts(&self) -> anyhow::Result { let package = match self.package.clone() { Some(_) if self.paths.len() > 2 => { - anyhow::bail!("`--package` is currently unsupported when providing more than one path argument"); + anyhow::bail!( + "`--package` is currently unsupported when providing more than one path argument" + ); } Some(PackageSpec { package, diff --git a/crates/wkg/src/oci.rs b/crates/wkg/src/oci.rs index a40eeae..a21670a 100644 --- a/crates/wkg/src/oci.rs +++ b/crates/wkg/src/oci.rs @@ -4,9 +4,9 @@ use anyhow::Context; use clap::{Args, Subcommand}; use docker_credential::DockerCredential; use oci_client::{ + Reference, client::{ClientConfig, ClientProtocol, PushResponse}, secrets::RegistryAuth, - Reference, }; use oci_wasm::{WasmClient, WasmConfig}; @@ -225,8 +225,8 @@ fn get_client(common: Common) -> WasmClient { #[cfg(test)] mod tests { use crate::oci::Auth; - use base64::{engine::general_purpose, Engine}; - use oci_client::{secrets::RegistryAuth, Reference}; + use base64::{Engine, engine::general_purpose}; + use oci_client::{Reference, secrets::RegistryAuth}; use serde_json::json; use tempfile::tempdir; @@ -235,7 +235,10 @@ mod tests { // NOTE(thomastaylor312): These have to run serially because we are setting an env var into_auth_should_read_docker_registry_credentials(); into_auth_should_other_registry_credentials(); - std::env::remove_var("DOCKER_CONFIG"); + // NOT-SAFE: this is likely causing race conditions + unsafe { + std::env::remove_var("DOCKER_CONFIG"); + } } fn into_auth_should_read_docker_registry_credentials() { @@ -267,7 +270,10 @@ mod tests { } }); std::fs::write(docker_config, auths.to_string()).unwrap(); - std::env::set_var("DOCKER_CONFIG", temp_docker_config.path().as_os_str()); + // NOT-SAFE: this is likely causing race conditions + unsafe { + std::env::set_var("DOCKER_CONFIG", temp_docker_config.path().as_os_str()); + } let auth = auth.into_auth(reference).unwrap(); assert_eq!(RegistryAuth::Basic(username, password), auth); } diff --git a/crates/wkg/tests/common.rs b/crates/wkg/tests/common.rs index ef222d2..7315ad8 100644 --- a/crates/wkg/tests/common.rs +++ b/crates/wkg/tests/common.rs @@ -6,12 +6,12 @@ use std::{ use oci_client::client::ClientConfig; use testcontainers::{ + ContainerAsync, GenericImage, ImageExt, core::{IntoContainerPort, WaitFor}, runners::AsyncRunner, - ContainerAsync, GenericImage, ImageExt, }; use tokio::{net::TcpListener, process::Command}; -use wasm_pkg_client::{oci::OciRegistryConfig, Config, CustomConfig, Registry, RegistryMetadata}; +use wasm_pkg_client::{Config, CustomConfig, Registry, RegistryMetadata, oci::OciRegistryConfig}; /// Returns an open port on localhost pub async fn find_open_port() -> u16 { diff --git a/crates/wkg/tests/e2e.rs b/crates/wkg/tests/e2e.rs index 10691ad..f41dfe1 100644 --- a/crates/wkg/tests/e2e.rs +++ b/crates/wkg/tests/e2e.rs @@ -7,8 +7,8 @@ mod common; #[cfg(feature = "docker-tests")] #[tokio::test] async fn build_and_publish_with_metadata() { - use oci_client::{client::ClientConfig, manifest::OciManifest, Reference}; - use wasm_pkg_core::manifest::{Manifest, MANIFEST_FILE_NAME}; + use oci_client::{Reference, client::ClientConfig, manifest::OciManifest}; + use wasm_pkg_core::manifest::{MANIFEST_FILE_NAME, Manifest}; let (config, registry, _container) = common::start_registry().await; From 34a8116cf657a3fe7692c9583171eb80836b2bd9 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Thu, 2 Jul 2026 09:23:19 -0500 Subject: [PATCH 15/16] revert(core,common): defer ansi impl Display impls --- Cargo.lock | 1 - crates/wasm-pkg-common/Cargo.toml | 4 --- crates/wasm-pkg-common/src/package.rs | 38 +++------------------------ crates/wasm-pkg-core/Cargo.toml | 5 ---- crates/wasm-pkg-core/src/resolver.rs | 3 +++ crates/wkg/Cargo.toml | 7 ++--- 6 files changed, 9 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4ed24e6..190dba9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5204,7 +5204,6 @@ dependencies = [ name = "wasm-pkg-common" version = "0.16.0" dependencies = [ - "anstyle", "anyhow", "bytes", "etcetera 0.11.0", diff --git a/crates/wasm-pkg-common/Cargo.toml b/crates/wasm-pkg-common/Cargo.toml index 86f5fdd..ebdcc95 100644 --- a/crates/wasm-pkg-common/Cargo.toml +++ b/crates/wasm-pkg-common/Cargo.toml @@ -14,14 +14,10 @@ registry-config = [ "dep:tokio", "dep:toml", ] -ansi-term-output = [ "dep:anstyle" ] -# running `cargo test` (implicit `--workspace` flag), leaks `ansi-term-output` from wkg -test = [] # Extra features to facilitate making working with OCI images easier oci_extras = [] [dependencies] -anstyle = { workspace = true, optional = true } anyhow = { workspace = true } bytes = { workspace = true } etcetera = { workspace = true, optional = true } diff --git a/crates/wasm-pkg-common/src/package.rs b/crates/wasm-pkg-common/src/package.rs index 8859dd9..c1de700 100644 --- a/crates/wasm-pkg-common/src/package.rs +++ b/crates/wasm-pkg-common/src/package.rs @@ -6,15 +6,6 @@ use crate::{Error, label::Label}; pub use semver::Version; -#[cfg(all(feature = "ansi-term-output", not(feature = "test")))] -pub(crate) mod ansi { - use anstyle::{Ansi256Color, AnsiColor, Style}; - - pub(crate) const LABEL: Style = AnsiColor::BrightBlue.on_default().bold(); - pub(crate) const VERSION: Style = AnsiColor::BrightRed.on_default(); - pub(crate) const SEP: Style = Ansi256Color(249).on_default(); -} - /// A package reference, consisting of kebab-case namespace and name. /// /// Ex: `wasm-pkg:client` @@ -44,16 +35,6 @@ impl PackageRef { impl std::fmt::Display for PackageRef { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - #[cfg(all(feature = "ansi-term-output", not(feature = "test")))] - { - use ansi::{LABEL, SEP}; - write!( - f, - "{LABEL}{}{LABEL:#}{SEP}:{SEP:#}{LABEL}{}{LABEL:#}", - self.namespace, self.name, - ) - } - #[cfg(not(all(feature = "ansi-term-output", not(feature = "test"))))] write!(f, "{}:{}", self.namespace, self.name) } } @@ -89,21 +70,10 @@ impl FromStr for PackageRef { } impl std::fmt::Display for PackageSpec { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match &self.version { - Some(version) => { - #[cfg(all(feature = "ansi-term-output", not(feature = "test")))] - { - use ansi::{SEP, VERSION}; - write!( - f, - "{}{SEP}@{SEP:#}{VERSION}{version}{VERSION:#}", - self.package, - ) - } - #[cfg(not(all(feature = "ansi-term-output", not(feature = "test"))))] - write!(f, "{}@{version}", self.package) - } - None => write!(f, "{}", self.package), + if let Some(version) = &self.version { + write!(f, "{}@{}", self.package, version) + } else { + write!(f, "{}", self.package) } } } diff --git a/crates/wasm-pkg-core/Cargo.toml b/crates/wasm-pkg-core/Cargo.toml index f116de4..37800f1 100644 --- a/crates/wasm-pkg-core/Cargo.toml +++ b/crates/wasm-pkg-core/Cargo.toml @@ -7,11 +7,6 @@ version.workspace = true authors.workspace = true license.workspace = true -[features] -ansi-term-output = ["wasm-pkg-common/ansi-term-output"] -# running `cargo test` (implicit `--workspace` flag), leaks `ansi-term-output` from wkg -test = ["wasm-pkg-common/test"] - [dependencies] anyhow = { workspace = true } futures-util = { workspace = true } diff --git a/crates/wasm-pkg-core/src/resolver.rs b/crates/wasm-pkg-core/src/resolver.rs index 1943c38..4a7bcbc 100644 --- a/crates/wasm-pkg-core/src/resolver.rs +++ b/crates/wasm-pkg-core/src/resolver.rs @@ -952,14 +952,17 @@ impl PublishPlan { impl std::fmt::Display for PublishPlan { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // TODO(mkatychev): handle with anstyle and anstream, passing in `anstream::AutoStream` for colour choice for id in self.dependents.nodes_iter() { let dep = &self.dependents[id]; + // initial dependency graph visualization let mut neighbors = self .dependents .neighbors_directed(id, Direction::Outgoing) .peekable(); if neighbors.peek().is_none() { + // tracing::debug!("{dep} has no dependents"); writeln!(f, "[{dep} has no dependents]")?; } else { writeln!(f, "[{dep}]")?; diff --git a/crates/wkg/Cargo.toml b/crates/wkg/Cargo.toml index 1754df0..473b974 100644 --- a/crates/wkg/Cargo.toml +++ b/crates/wkg/Cargo.toml @@ -27,16 +27,13 @@ tempfile = { workspace = true } tokio = { workspace = true, features = ["macros", "rt"] } tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["ansi"] } -wasm-pkg-common = { workspace = true, features = ["ansi-term-output"] } +wasm-pkg-common = { workspace = true } wasm-pkg-client = { workspace = true } wit-component = { workspace = true } -wasm-pkg-core = { workspace = true, features = ["ansi-term-output"] } +wasm-pkg-core = { workspace = true } [dev-dependencies] -wasm-pkg-core = { workspace = true, features = ["test"] } -wasm-pkg-common = { workspace = true, features = ["test"] } base64 = { workspace = true } serde_json = { workspace = true } tempfile = { workspace = true } testcontainers = { workspace = true } -anstream = { workspace = true, features = ["test"] } From f9092634b74a6975549bbf8ea578f31aa528749d Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Thu, 2 Jul 2026 09:30:55 -0500 Subject: [PATCH 16/16] chore: add anstream test flag to wkg dev --- crates/wkg/Cargo.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/wkg/Cargo.toml b/crates/wkg/Cargo.toml index 473b974..d52cf28 100644 --- a/crates/wkg/Cargo.toml +++ b/crates/wkg/Cargo.toml @@ -27,12 +27,13 @@ tempfile = { workspace = true } tokio = { workspace = true, features = ["macros", "rt"] } tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["ansi"] } -wasm-pkg-common = { workspace = true } wasm-pkg-client = { workspace = true } -wit-component = { workspace = true } +wasm-pkg-common = { workspace = true } wasm-pkg-core = { workspace = true } +wit-component = { workspace = true } [dev-dependencies] +anstream = { workspace = true, features = ["test"] } base64 = { workspace = true } serde_json = { workspace = true } tempfile = { workspace = true }