From 72b018adec782757365ca1a5b8bb04d6afc32232 Mon Sep 17 00:00:00 2001 From: Christoph Herzog Date: Fri, 24 Oct 2025 05:12:42 +0200 Subject: [PATCH 1/3] chore(cli): commands/run code quality cleanup The mod.rs is long and contains a lot of things. This commit: * splits funcitonality out into submodules (targetrs, runtime.rs, package_source.rs) * Renames the shadowing PackageSource to CliPackageSource to avoid the renamed import and name confusion * Fixes some other small code quality issues (eg Self vs in impls) --- lib/cli/src/commands/run/capabilities/mod.rs | 10 +- lib/cli/src/commands/run/capabilities/net.rs | 2 +- lib/cli/src/commands/run/mod.rs | 451 +------------------ lib/cli/src/commands/run/package_source.rs | 79 ++++ lib/cli/src/commands/run/runtime.rs | 250 ++++++++++ lib/cli/src/commands/run/target.rs | 152 +++++++ lib/cli/src/commands/run/wasi.rs | 2 +- 7 files changed, 502 insertions(+), 444 deletions(-) create mode 100644 lib/cli/src/commands/run/package_source.rs create mode 100644 lib/cli/src/commands/run/runtime.rs create mode 100644 lib/cli/src/commands/run/target.rs diff --git a/lib/cli/src/commands/run/capabilities/mod.rs b/lib/cli/src/commands/run/capabilities/mod.rs index ada750bd57d..43e3c36bc97 100644 --- a/lib/cli/src/commands/run/capabilities/mod.rs +++ b/lib/cli/src/commands/run/capabilities/mod.rs @@ -1,6 +1,6 @@ use crate::config::WasmerEnv; -use super::PackageSource; +use super::CliPackageSource; use anyhow::anyhow; use sha2::{Digest, Sha256}; use std::{ @@ -25,7 +25,7 @@ pub(crate) struct PkgCapabilityCache { pub(crate) fn get_capability_cache_path( env: &WasmerEnv, - input: &PackageSource, + input: &CliPackageSource, ) -> anyhow::Result { let registry_name = env .registry_public_url()? @@ -36,7 +36,7 @@ pub(crate) fn get_capability_cache_path( // We don't have the bytes of the module yet, but we still want to have the // package-capabilities cache be as close to an actual identifier as possible. let package_cache_path = match &input { - PackageSource::File(f) => { + CliPackageSource::File(f) => { let full_path = f.canonicalize()?.to_path_buf(); let metadata = full_path .parent() @@ -61,7 +61,7 @@ pub(crate) fn get_capability_cache_path( format!("path_{}.json", hex::encode(hash.finalize())) } - PackageSource::Dir(f) => { + CliPackageSource::Dir(f) => { let full_path = f.canonicalize()?.to_path_buf(); let metadata = full_path.metadata()?.modified()?; @@ -82,7 +82,7 @@ pub(crate) fn get_capability_cache_path( format!("path_{}.json", hex::encode(hash.finalize())) } - PackageSource::Package(p) => match p { + CliPackageSource::Package(p) => match p { PackageSpecifier::Ident(id) => match id { wasmer_config::package::PackageIdent::Named(n) => format!( "ident_{}_{}", diff --git a/lib/cli/src/commands/run/capabilities/net.rs b/lib/cli/src/commands/run/capabilities/net.rs index 7f12fd73681..d6610260adb 100644 --- a/lib/cli/src/commands/run/capabilities/net.rs +++ b/lib/cli/src/commands/run/capabilities/net.rs @@ -7,7 +7,7 @@ use std::{ time::Duration, }; -use super::{super::PackageSource, PkgCapabilityCache}; +use super::{super::CliPackageSource, PkgCapabilityCache}; use anyhow::Context; use colored::Colorize; use dialoguer::theme::ColorfulTheme; diff --git a/lib/cli/src/commands/run/mod.rs b/lib/cli/src/commands/run/mod.rs index af422a3ce7c..505e1cddf97 100644 --- a/lib/cli/src/commands/run/mod.rs +++ b/lib/cli/src/commands/run/mod.rs @@ -1,6 +1,9 @@ #![allow(missing_docs, unused)] mod capabilities; +mod package_source; +mod runtime; +mod target; mod wasi; use std::{ @@ -35,7 +38,7 @@ use wasmer_types::{Features, target::Target}; #[cfg(feature = "compiler")] use wasmer_compiler::ArtifactBuild; -use wasmer_config::package::PackageSource as PackageSpecifier; +use wasmer_config::package::PackageSource; use wasmer_package::utils::from_disk; use wasmer_types::ModuleHash; @@ -67,6 +70,10 @@ use crate::{ error::PrettyError, logging::Output, }; +use self::{ + package_source::CliPackageSource, runtime::MonitoringRuntime, target::ExecutableTarget, +}; + const TICK: Duration = Duration::from_millis(250); /// The unstable `wasmer run` subcommand. @@ -93,8 +100,8 @@ pub struct Run { #[clap(name = "COREDUMP_PATH", long)] coredump_on_trap: Option, /// The file, URL, or package to run. - #[clap(value_parser = PackageSource::infer)] - input: PackageSource, + #[clap(value_parser = CliPackageSource::infer)] + input: CliPackageSource, /// Command-line arguments passed to the package args: Vec, /// Hashing algorithm to be used for module hash @@ -139,7 +146,7 @@ impl Run { // Try to detect WebAssembly features before selecting a backend tracing::info!("Input source: {:?}", self.input); - if let PackageSource::File(path) = &self.input { + if let CliPackageSource::File(path) = &self.input { tracing::info!("Input file path: {}", path.display()); // Try to read and detect any file that exists, regardless of extension @@ -186,7 +193,7 @@ impl Run { } None => { // No WebAssembly file available for analysis, check if we have a webc package - if let PackageSource::Package(pkg_source) = &self.input { + if let CliPackageSource::Package(pkg_source) = &self.input { tracing::info!("Checking package for WebAssembly features: {}", pkg_source); self.rt.get_engine(&Target::default())? } else { @@ -379,7 +386,8 @@ impl Run { let mut dependencies = Vec::new(); for name in &self.wasi.uses { - let specifier = PackageSpecifier::from_str(name) + let specifier = name + .parse::() .with_context(|| format!("Unable to parse \"{name}\" as a package specifier"))?; let pkg = { let specifier = specifier.clone(); @@ -669,205 +677,6 @@ fn parse_value(s: &str, ty: wasmer_types::Type) -> Result { Ok(value) } -/// The input that was passed in via the command-line. -#[derive(Debug, Clone, PartialEq)] -enum PackageSource { - /// A file on disk (`*.wasm`, `*.webc`, etc.). - File(PathBuf), - /// A directory containing a `wasmer.toml` file - Dir(PathBuf), - /// A package to be downloaded (a URL, package name, etc.) - Package(PackageSpecifier), -} - -impl PackageSource { - fn infer(s: &str) -> Result { - let path = Path::new(s); - if path.is_file() { - return Ok(PackageSource::File(path.to_path_buf())); - } else if path.is_dir() { - return Ok(PackageSource::Dir(path.to_path_buf())); - } - - if let Ok(pkg) = PackageSpecifier::from_str(s) { - return Ok(PackageSource::Package(pkg)); - } - - Err(anyhow::anyhow!( - "Unable to resolve \"{s}\" as a URL, package name, or file on disk" - )) - } - - /// Try to resolve the [`PackageSource`] to an executable artifact. - /// - /// This will try to automatically download and cache any resources from the - /// internet. - #[tracing::instrument(level = "debug", skip_all)] - fn resolve_target( - &self, - rt: &Arc, - pb: &ProgressBar, - ) -> Result { - match self { - PackageSource::File(path) => ExecutableTarget::from_file(path, rt, pb), - PackageSource::Dir(d) => ExecutableTarget::from_dir(d, rt, pb), - PackageSource::Package(pkg) => { - pb.set_message("Loading from the registry"); - let inner_pck = pkg.clone(); - let inner_rt = rt.clone(); - let pkg = rt.task_manager().spawn_and_block_on(async move { - BinaryPackage::from_registry(&inner_pck, inner_rt.as_ref()).await - })??; - Ok(ExecutableTarget::Package(Box::new(pkg))) - } - } - } -} - -impl Display for PackageSource { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - PackageSource::File(path) | PackageSource::Dir(path) => write!(f, "{}", path.display()), - PackageSource::Package(p) => write!(f, "{p}"), - } - } -} - -/// We've been given the path for a file... What does it contain and how should -/// that be run? -#[derive(Debug, Clone)] -enum TargetOnDisk { - WebAssemblyBinary, - Wat, - LocalWebc, - Artifact, -} - -impl TargetOnDisk { - fn from_file(path: &Path) -> Result { - // Normally the first couple hundred bytes is enough to figure - // out what type of file this is. - let mut buffer = [0_u8; 512]; - - let mut f = File::open(path) - .with_context(|| format!("Unable to open \"{}\" for reading", path.display()))?; - let bytes_read = f.read(&mut buffer)?; - - let leading_bytes = &buffer[..bytes_read]; - - if wasmer::is_wasm(leading_bytes) { - return Ok(TargetOnDisk::WebAssemblyBinary); - } - - if webc::detect(leading_bytes).is_ok() { - return Ok(TargetOnDisk::LocalWebc); - } - - #[cfg(feature = "compiler")] - if ArtifactBuild::is_deserializable(leading_bytes) { - return Ok(TargetOnDisk::Artifact); - } - - // If we can't figure out the file type based on its content, fall back - // to checking the extension. - - match path.extension().and_then(|s| s.to_str()) { - Some("wat") => Ok(TargetOnDisk::Wat), - Some("wasm") => Ok(TargetOnDisk::WebAssemblyBinary), - Some("webc") => Ok(TargetOnDisk::LocalWebc), - Some("wasmu") => Ok(TargetOnDisk::WebAssemblyBinary), - _ => bail!("Unable to determine how to execute \"{}\"", path.display()), - } - } -} - -#[derive(Debug, Clone)] -#[allow(clippy::large_enum_variant)] -enum ExecutableTarget { - WebAssembly { - module: Module, - module_hash: ModuleHash, - path: PathBuf, - }, - Package(Box), -} - -impl ExecutableTarget { - /// Try to load a Wasmer package from a directory containing a `wasmer.toml` - /// file. - #[tracing::instrument(level = "debug", skip_all)] - fn from_dir( - dir: &Path, - runtime: &Arc, - pb: &ProgressBar, - ) -> Result { - pb.set_message(format!("Loading \"{}\" into memory", dir.display())); - pb.set_message("Resolving dependencies"); - let inner_runtime = runtime.clone(); - let pkg = runtime.task_manager().spawn_and_block_on({ - let path = dir.to_path_buf(); - - async move { BinaryPackage::from_dir(&path, inner_runtime.as_ref()).await } - })??; - - Ok(ExecutableTarget::Package(Box::new(pkg))) - } - - /// Try to load a file into something that can be used to run it. - #[tracing::instrument(level = "debug", skip_all)] - fn from_file( - path: &Path, - runtime: &Arc, - pb: &ProgressBar, - ) -> Result { - pb.set_message(format!("Loading from \"{}\"", path.display())); - - match TargetOnDisk::from_file(path)? { - TargetOnDisk::WebAssemblyBinary | TargetOnDisk::Wat => { - let wasm = std::fs::read(path)?; - let module_data = HashedModuleData::new(wasm); - let module_hash = *module_data.hash(); - - pb.set_message("Compiling to WebAssembly"); - let module = runtime - .load_hashed_module_sync(module_data, None) - .with_context(|| format!("Unable to compile \"{}\"", path.display()))?; - - Ok(ExecutableTarget::WebAssembly { - module, - module_hash, - path: path.to_path_buf(), - }) - } - TargetOnDisk::Artifact => { - let engine = runtime.engine(); - pb.set_message("Deserializing pre-compiled WebAssembly module"); - let module = unsafe { Module::deserialize_from_file(&engine, path)? }; - - let module_hash = module.info().hash.ok_or_else(|| { - anyhow::Error::msg("module hash is not present in the artifact") - })?; - - Ok(ExecutableTarget::WebAssembly { - module, - module_hash, - path: path.to_path_buf(), - }) - } - TargetOnDisk::LocalWebc => { - let container = from_disk(path)?; - pb.set_message("Resolving dependencies"); - - let inner_runtime = runtime.clone(); - let pkg = runtime.task_manager().spawn_and_block_on(async move { - BinaryPackage::from_webc(&container, inner_runtime.as_ref()).await - })??; - Ok(ExecutableTarget::Package(Box::new(pkg))) - } - } - } -} - #[cfg(feature = "coredump")] fn generate_coredump(err: &Error, source_name: String, coredump_path: &Path) -> Result<(), Error> { let err: &wasmer::RuntimeError = match err.downcast_ref() { @@ -989,235 +798,3 @@ fn get_exit_code( None } - -#[derive(Debug)] -struct MonitoringRuntime { - runtime: Arc, - progress: ProgressBar, - quiet_mode: bool, -} - -impl MonitoringRuntime { - fn new(runtime: R, progress: ProgressBar, quiet_mode: bool) -> Self { - MonitoringRuntime { - runtime: Arc::new(runtime), - progress, - quiet_mode, - } - } -} - -impl wasmer_wasix::Runtime for MonitoringRuntime { - fn networking(&self) -> &virtual_net::DynVirtualNetworking { - self.runtime.networking() - } - - fn task_manager(&self) -> &Arc { - self.runtime.task_manager() - } - - fn package_loader( - &self, - ) -> Arc { - let inner = self.runtime.package_loader(); - Arc::new(MonitoringPackageLoader { - inner, - progress: self.progress.clone(), - }) - } - - fn module_cache( - &self, - ) -> Arc { - self.runtime.module_cache() - } - - fn source(&self) -> Arc { - let inner = self.runtime.source(); - Arc::new(MonitoringSource { - inner, - progress: self.progress.clone(), - }) - } - - fn engine(&self) -> wasmer::Engine { - self.runtime.engine() - } - - fn new_store(&self) -> wasmer::Store { - self.runtime.new_store() - } - - fn http_client(&self) -> Option<&wasmer_wasix::http::DynHttpClient> { - self.runtime.http_client() - } - - fn tty(&self) -> Option<&(dyn wasmer_wasix::os::TtyBridge + Send + Sync)> { - self.runtime.tty() - } - - #[cfg(feature = "journal")] - fn read_only_journals<'a>( - &'a self, - ) -> Box> + 'a> { - self.runtime.read_only_journals() - } - - #[cfg(feature = "journal")] - fn writable_journals<'a>( - &'a self, - ) -> Box> + 'a> { - self.runtime.writable_journals() - } - - #[cfg(feature = "journal")] - fn active_journal(&self) -> Option<&'_ wasmer_wasix::journal::DynJournal> { - self.runtime.active_journal() - } - - fn load_hashed_module( - &self, - module: HashedModuleData, - engine: Option<&Engine>, - ) -> BoxFuture<'_, Result> { - let hash = *module.hash(); - let fut = self.runtime.load_hashed_module(module, engine); - Box::pin(compile_with_progress(fut, hash, None, self.quiet_mode)) - } - - fn load_hashed_module_sync( - &self, - wasm: HashedModuleData, - engine: Option<&Engine>, - ) -> Result { - let hash = *wasm.hash(); - compile_with_progress_sync( - || self.runtime.load_hashed_module_sync(wasm, engine), - &hash, - None, - self.quiet_mode, - ) - } - - fn load_command_module( - &self, - cmd: &BinaryPackageCommand, - ) -> BoxFuture<'_, Result> { - let fut = self.runtime.load_command_module(cmd); - - Box::pin(compile_with_progress( - fut, - *cmd.hash(), - Some(cmd.name().to_owned()), - self.quiet_mode, - )) - } - - fn load_command_module_sync( - &self, - cmd: &wasmer_wasix::bin_factory::BinaryPackageCommand, - ) -> Result { - compile_with_progress_sync( - || self.runtime.load_command_module_sync(cmd), - cmd.hash(), - Some(cmd.name()), - self.quiet_mode, - ) - } -} - -async fn compile_with_progress<'a, F, T>( - fut: F, - hash: ModuleHash, - name: Option, - quiet_mode: bool, -) -> T -where - F: std::future::Future + Send + 'a, - T: Send + 'static, -{ - let mut pb = new_progressbar_compile(&hash, name.as_deref(), quiet_mode); - let res = fut.await; - pb.finish_and_clear(); - res -} - -fn compile_with_progress_sync( - f: F, - hash: &ModuleHash, - name: Option<&str>, - quiet_mode: bool, -) -> T -where - F: FnOnce() -> T, -{ - let mut pb = new_progressbar_compile(hash, name, quiet_mode); - let res = f(); - pb.finish_and_clear(); - res -} - -fn new_progressbar_compile(hash: &ModuleHash, name: Option<&str>, quiet_mode: bool) -> ProgressBar { - // Only show a spinner if we're running in a TTY - let hash = hash.to_string(); - let hash = &hash[0..8]; - if !quiet_mode && std::io::stderr().is_terminal() { - let msg = if let Some(name) = name { - format!("Compiling WebAssembly module for command '{name}' ({hash})...") - } else { - format!("Compiling WebAssembly module {hash}...") - }; - let pb = ProgressBar::new_spinner().with_message(msg); - pb.enable_steady_tick(Duration::from_millis(100)); - pb - } else { - ProgressBar::hidden() - } -} - -#[derive(Debug)] -struct MonitoringSource { - inner: Arc, - progress: ProgressBar, -} - -#[async_trait::async_trait] -impl wasmer_wasix::runtime::resolver::Source for MonitoringSource { - async fn query( - &self, - package: &PackageSpecifier, - ) -> Result, QueryError> { - self.progress.set_message(format!("Looking up {package}")); - self.inner.query(package).await - } -} - -#[derive(Debug)] -struct MonitoringPackageLoader { - inner: Arc, - progress: ProgressBar, -} - -#[async_trait::async_trait] -impl wasmer_wasix::runtime::package_loader::PackageLoader for MonitoringPackageLoader { - async fn load( - &self, - summary: &wasmer_wasix::runtime::resolver::PackageSummary, - ) -> Result { - let pkg_id = summary.package_id(); - self.progress.set_message(format!("Downloading {pkg_id}")); - - self.inner.load(summary).await - } - - async fn load_package_tree( - &self, - root: &Container, - resolution: &wasmer_wasix::runtime::resolver::Resolution, - root_is_local_dir: bool, - ) -> Result { - self.inner - .load_package_tree(root, resolution, root_is_local_dir) - .await - } -} diff --git a/lib/cli/src/commands/run/package_source.rs b/lib/cli/src/commands/run/package_source.rs new file mode 100644 index 00000000000..92c5d76faa2 --- /dev/null +++ b/lib/cli/src/commands/run/package_source.rs @@ -0,0 +1,79 @@ +use std::{ + path::{Path, PathBuf}, + sync::Arc, +}; + +use anyhow::Error; +use indicatif::ProgressBar; +use wasmer_config::package::PackageSource; +use wasmer_wasix::{ + Runtime, bin_factory::BinaryPackage, runtime::task_manager::VirtualTaskManagerExt as _, +}; + +use super::ExecutableTarget; + +/// CLI representation of a target to execute. +#[derive(Debug, Clone, PartialEq)] +pub enum CliPackageSource { + /// A file on disk (`*.wasm`, `*.webc`, etc.). + File(PathBuf), + /// A directory containing a `wasmer.toml` file + Dir(PathBuf), + /// A package to be downloaded (a URL, package name, etc.) + Package(PackageSource), +} + +impl CliPackageSource { + pub fn infer(s: &str) -> Result { + let path = Path::new(s); + if path.is_file() { + return Ok(Self::File(path.to_path_buf())); + } else if path.is_dir() { + return Ok(Self::Dir(path.to_path_buf())); + } + + if let Ok(pkg) = s.parse::() { + return Ok(Self::Package(pkg)); + } + + Err(anyhow::anyhow!( + "Unable to resolve \"{s}\" as a URL, package name, or file on disk" + )) + } + + /// Try to resolve the [`PackageSource`] to an executable artifact. + /// + /// This will try to automatically download and cache any resources from the + /// internet. + #[tracing::instrument(level = "debug", skip_all)] + pub fn resolve_target( + &self, + rt: &Arc, + pb: &ProgressBar, + ) -> Result { + match self { + Self::File(path) => ExecutableTarget::from_file(path, rt, pb), + Self::Dir(d) => ExecutableTarget::from_dir(d, rt, pb), + Self::Package(pkg) => { + pb.set_message("Loading from the registry"); + let inner_pck = pkg.clone(); + let inner_rt = rt.clone(); + let pkg = rt.task_manager().spawn_and_block_on(async move { + BinaryPackage::from_registry(&inner_pck, inner_rt.as_ref()).await + })??; + Ok(ExecutableTarget::Package(Box::new(pkg))) + } + } + } +} + +impl std::fmt::Display for CliPackageSource { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::File(path) | Self::Dir(path) => { + write!(f, "{}", path.display()) + } + Self::Package(p) => write!(f, "{p}"), + } + } +} diff --git a/lib/cli/src/commands/run/runtime.rs b/lib/cli/src/commands/run/runtime.rs new file mode 100644 index 00000000000..64dd4d40d40 --- /dev/null +++ b/lib/cli/src/commands/run/runtime.rs @@ -0,0 +1,250 @@ +//! Provides CLI-specific Wasix components. + +use anyhow::Error; +use std::{sync::Arc, time::Duration}; + +use futures::future::BoxFuture; +use indicatif::ProgressBar; +use is_terminal::IsTerminal as _; +use wasmer::{Engine, Module}; +use wasmer_config::package::PackageSource; +use wasmer_types::ModuleHash; +use wasmer_wasix::{ + SpawnError, + bin_factory::{BinaryPackage, BinaryPackageCommand}, + runtime::{ + module_cache::HashedModuleData, + resolver::{PackageSummary, QueryError}, + }, +}; +use webc::Container; + +/// Special wasix runtime implementation for the CLI. +/// +/// Wraps an undelrying runtime and adds progress monitoring for package +/// compilation. +#[derive(Debug)] +pub struct MonitoringRuntime { + pub runtime: Arc, + progress: ProgressBar, + quiet_mode: bool, +} + +impl MonitoringRuntime { + pub fn new(runtime: R, progress: ProgressBar, quiet_mode: bool) -> Self { + MonitoringRuntime { + runtime: Arc::new(runtime), + progress, + quiet_mode, + } + } +} + +impl wasmer_wasix::Runtime for MonitoringRuntime { + fn networking(&self) -> &virtual_net::DynVirtualNetworking { + self.runtime.networking() + } + + fn task_manager(&self) -> &Arc { + self.runtime.task_manager() + } + + fn package_loader( + &self, + ) -> Arc { + let inner = self.runtime.package_loader(); + Arc::new(MonitoringPackageLoader { + inner, + progress: self.progress.clone(), + }) + } + + fn module_cache( + &self, + ) -> Arc { + self.runtime.module_cache() + } + + fn source(&self) -> Arc { + let inner = self.runtime.source(); + Arc::new(MonitoringSource { + inner, + progress: self.progress.clone(), + }) + } + + fn engine(&self) -> Engine { + self.runtime.engine() + } + + fn new_store(&self) -> wasmer::Store { + self.runtime.new_store() + } + + fn http_client(&self) -> Option<&wasmer_wasix::http::DynHttpClient> { + self.runtime.http_client() + } + + fn tty(&self) -> Option<&(dyn wasmer_wasix::os::TtyBridge + Send + Sync)> { + self.runtime.tty() + } + + #[cfg(feature = "journal")] + fn read_only_journals<'a>( + &'a self, + ) -> Box> + 'a> { + self.runtime.read_only_journals() + } + + #[cfg(feature = "journal")] + fn writable_journals<'a>( + &'a self, + ) -> Box> + 'a> { + self.runtime.writable_journals() + } + + #[cfg(feature = "journal")] + fn active_journal(&self) -> Option<&'_ wasmer_wasix::journal::DynJournal> { + self.runtime.active_journal() + } + + fn load_hashed_module( + &self, + module: HashedModuleData, + engine: Option<&Engine>, + ) -> BoxFuture<'_, Result> { + let hash = *module.hash(); + let fut = self.runtime.load_hashed_module(module, engine); + Box::pin(compile_with_progress(fut, hash, None, self.quiet_mode)) + } + + fn load_hashed_module_sync( + &self, + wasm: HashedModuleData, + engine: Option<&Engine>, + ) -> Result { + let hash = *wasm.hash(); + compile_with_progress_sync( + || self.runtime.load_hashed_module_sync(wasm, engine), + &hash, + None, + self.quiet_mode, + ) + } + + fn load_command_module( + &self, + cmd: &BinaryPackageCommand, + ) -> BoxFuture<'_, Result> { + let fut = self.runtime.load_command_module(cmd); + + Box::pin(compile_with_progress( + fut, + *cmd.hash(), + Some(cmd.name().to_owned()), + self.quiet_mode, + )) + } + + fn load_command_module_sync( + &self, + cmd: &wasmer_wasix::bin_factory::BinaryPackageCommand, + ) -> Result { + compile_with_progress_sync( + || self.runtime.load_command_module_sync(cmd), + cmd.hash(), + Some(cmd.name()), + self.quiet_mode, + ) + } +} + +async fn compile_with_progress<'a, F, T>( + fut: F, + hash: ModuleHash, + name: Option, + quiet_mode: bool, +) -> T +where + F: std::future::Future + Send + 'a, + T: Send + 'static, +{ + let mut pb = new_progressbar_compile(&hash, name.as_deref(), quiet_mode); + let res = fut.await; + pb.finish_and_clear(); + res +} + +fn compile_with_progress_sync( + f: F, + hash: &ModuleHash, + name: Option<&str>, + quiet_mode: bool, +) -> T +where + F: FnOnce() -> T, +{ + let mut pb = new_progressbar_compile(hash, name, quiet_mode); + let res = f(); + pb.finish_and_clear(); + res +} + +fn new_progressbar_compile(hash: &ModuleHash, name: Option<&str>, quiet_mode: bool) -> ProgressBar { + // Only show a spinner if we're running in a TTY + let hash = hash.to_string(); + let hash = &hash[0..8]; + if !quiet_mode && std::io::stderr().is_terminal() { + let msg = if let Some(name) = name { + format!("Compiling WebAssembly module for command '{name}' ({hash})...") + } else { + format!("Compiling WebAssembly module {hash}...") + }; + let pb = ProgressBar::new_spinner().with_message(msg); + pb.enable_steady_tick(Duration::from_millis(100)); + pb + } else { + ProgressBar::hidden() + } +} + +#[derive(Debug)] +struct MonitoringSource { + inner: Arc, + progress: ProgressBar, +} + +#[async_trait::async_trait] +impl wasmer_wasix::runtime::resolver::Source for MonitoringSource { + async fn query(&self, package: &PackageSource) -> Result, QueryError> { + self.progress.set_message(format!("Looking up {package}")); + self.inner.query(package).await + } +} + +#[derive(Debug)] +struct MonitoringPackageLoader { + inner: Arc, + progress: ProgressBar, +} + +#[async_trait::async_trait] +impl wasmer_wasix::runtime::package_loader::PackageLoader for MonitoringPackageLoader { + async fn load(&self, summary: &PackageSummary) -> Result { + let pkg_id = summary.package_id(); + self.progress.set_message(format!("Downloading {pkg_id}")); + + self.inner.load(summary).await + } + + async fn load_package_tree( + &self, + root: &Container, + resolution: &wasmer_wasix::runtime::resolver::Resolution, + root_is_local_dir: bool, + ) -> Result { + self.inner + .load_package_tree(root, resolution, root_is_local_dir) + .await + } +} diff --git a/lib/cli/src/commands/run/target.rs b/lib/cli/src/commands/run/target.rs new file mode 100644 index 00000000000..fc056891fb2 --- /dev/null +++ b/lib/cli/src/commands/run/target.rs @@ -0,0 +1,152 @@ +use std::{ + fs::File, + io::Read as _, + path::{Path, PathBuf}, + sync::Arc, +}; + +use anyhow::{Context as _, Error, bail}; +use indicatif::ProgressBar; +use wasmer::Module; +use wasmer_types::ModuleHash; +use wasmer_wasix::{ + Runtime, + bin_factory::BinaryPackage, + runtime::{module_cache::HashedModuleData, task_manager::VirtualTaskManagerExt as _}, +}; +#[cfg(feature = "compiler")] +use wasmer_compiler::ArtifactBuild; + +/// We've been given the path for a file... What does it contain and how should +/// that be run? +#[derive(Debug, Clone)] +pub enum TargetOnDisk { + WebAssemblyBinary, + Wat, + LocalWebc, + Artifact, +} + +impl TargetOnDisk { + pub fn from_file(path: &Path) -> Result { + // Normally the first couple hundred bytes is enough to figure + // out what type of file this is. + let mut buffer = [0_u8; 512]; + + let mut f = File::open(path) + .with_context(|| format!("Unable to open \"{}\" for reading", path.display()))?; + let bytes_read = f.read(&mut buffer)?; + + let leading_bytes = &buffer[..bytes_read]; + + if wasmer::is_wasm(leading_bytes) { + return Ok(TargetOnDisk::WebAssemblyBinary); + } + + if webc::detect(leading_bytes).is_ok() { + return Ok(TargetOnDisk::LocalWebc); + } + + #[cfg(feature = "compiler")] + if ArtifactBuild::is_deserializable(leading_bytes) { + return Ok(TargetOnDisk::Artifact); + } + + // If we can't figure out the file type based on its content, fall back + // to checking the extension. + + match path.extension().and_then(|s| s.to_str()) { + Some("wat") => Ok(TargetOnDisk::Wat), + Some("wasm") => Ok(TargetOnDisk::WebAssemblyBinary), + Some("webc") => Ok(TargetOnDisk::LocalWebc), + Some("wasmu") => Ok(TargetOnDisk::WebAssemblyBinary), + _ => bail!("Unable to determine how to execute \"{}\"", path.display()), + } + } +} + +#[derive(Debug, Clone)] +pub enum ExecutableTarget { + WebAssembly { + module: Module, + module_hash: ModuleHash, + path: PathBuf, + }, + Package(Box), +} + +impl ExecutableTarget { + /// Try to load a Wasmer package from a directory containing a `wasmer.toml` + /// file. + #[tracing::instrument(level = "debug", skip_all)] + pub fn from_dir( + dir: &Path, + runtime: &Arc, + pb: &ProgressBar, + ) -> Result { + pb.set_message(format!("Loading \"{}\" into memory", dir.display())); + pb.set_message("Resolving dependencies"); + let inner_runtime = runtime.clone(); + let pkg = runtime.task_manager().spawn_and_block_on({ + let path = dir.to_path_buf(); + + async move { BinaryPackage::from_dir(&path, inner_runtime.as_ref()).await } + })??; + + Ok(ExecutableTarget::Package(Box::new(pkg))) + } + + /// Try to load a file into something that can be used to run it. + #[tracing::instrument(level = "debug", skip_all)] + pub fn from_file( + path: &Path, + runtime: &Arc, + pb: &ProgressBar, + ) -> Result { + pb.set_message(format!("Loading from \"{}\"", path.display())); + + match TargetOnDisk::from_file(path)? { + TargetOnDisk::WebAssemblyBinary | TargetOnDisk::Wat => { + let wasm = std::fs::read(path)?; + let module_data = HashedModuleData::new(wasm); + let module_hash = *module_data.hash(); + + pb.set_message("Compiling to WebAssembly"); + let module = runtime + .load_hashed_module_sync(module_data, None) + .with_context(|| format!("Unable to compile \"{}\"", path.display()))?; + + Ok(ExecutableTarget::WebAssembly { + module, + module_hash, + path: path.to_path_buf(), + }) + } + TargetOnDisk::Artifact => { + let engine = runtime.engine(); + pb.set_message("Deserializing pre-compiled WebAssembly module"); + let module = unsafe { Module::deserialize_from_file(&engine, path)? }; + + let module_hash = module.info().hash.ok_or_else(|| { + anyhow::Error::msg("module hash is not present in the artifact") + })?; + + Ok(ExecutableTarget::WebAssembly { + module, + module_hash, + path: path.to_path_buf(), + }) + } + TargetOnDisk::LocalWebc => { + let container = wasmer_package::utils::from_disk(path)?; + pb.set_message("Resolving dependencies"); + + let inner_runtime = runtime.clone(); + let pkg = runtime.task_manager().spawn_and_block_on(async move { + BinaryPackage::from_webc(&container, inner_runtime.as_ref()).await + })??; + Ok(ExecutableTarget::Package(Box::new(pkg))) + } + } + } +} diff --git a/lib/cli/src/commands/run/wasi.rs b/lib/cli/src/commands/run/wasi.rs index 666d3756801..1ec5a0bb547 100644 --- a/lib/cli/src/commands/run/wasi.rs +++ b/lib/cli/src/commands/run/wasi.rs @@ -51,7 +51,7 @@ use crate::{ }; use super::{ - ExecutableTarget, PackageSource, + CliPackageSource, ExecutableTarget, capabilities::{self, PkgCapabilityCache}, }; From 5e8c0c7319ba98599ec78ea23d39a5caae6be116 Mon Sep 17 00:00:00 2001 From: Christoph Herzog Date: Fri, 24 Oct 2025 06:05:31 +0200 Subject: [PATCH 2/3] chore(cli): MonitoringRuntime progress bar cleanup * Use a single progress bar * Show bar again if it was hidden * Remove code duplication for quiet flag handling --- lib/cli/src/commands/run/mod.rs | 21 ++--- lib/cli/src/commands/run/runtime.rs | 121 ++++++++++++++++++---------- lib/cli/src/logging.rs | 5 ++ 3 files changed, 96 insertions(+), 51 deletions(-) diff --git a/lib/cli/src/commands/run/mod.rs b/lib/cli/src/commands/run/mod.rs index 505e1cddf97..51c5223c05a 100644 --- a/lib/cli/src/commands/run/mod.rs +++ b/lib/cli/src/commands/run/mod.rs @@ -23,7 +23,6 @@ use anyhow::{Context, Error, anyhow, bail}; use clap::{Parser, ValueEnum}; use futures::future::BoxFuture; use indicatif::{MultiProgress, ProgressBar}; -use is_terminal::IsTerminal as _; use once_cell::sync::Lazy; use tempfile::NamedTempFile; use url::Url; @@ -227,8 +226,11 @@ impl Run { // This is a slow operation, so let's temporarily wrap the runtime with // something that displays progress - let monitoring_runtime = - Arc::new(MonitoringRuntime::new(runtime, pb.clone(), output.quiet)); + let monitoring_runtime = Arc::new(MonitoringRuntime::new( + runtime, + pb.clone(), + output.is_quiet_or_no_tty(), + )); let runtime: Arc = monitoring_runtime.runtime.clone(); let monitoring_runtime: Arc = monitoring_runtime; @@ -303,12 +305,13 @@ impl Run { preferred_webc_version, )?; - let new_runtime = Arc::new(MonitoringRuntime::new( - new_runtime, - pb.clone(), - output.quiet, - )); - return self.execute_webc(&pkg, new_runtime); + let new_runtime = Arc::new(MonitoringRuntime::new( + new_runtime, + pb.clone(), + output.is_quiet_or_no_tty(), + )); + return self.execute_webc(&pkg, new_runtime); + } } } } diff --git a/lib/cli/src/commands/run/runtime.rs b/lib/cli/src/commands/run/runtime.rs index 64dd4d40d40..638a38787fa 100644 --- a/lib/cli/src/commands/run/runtime.rs +++ b/lib/cli/src/commands/run/runtime.rs @@ -1,8 +1,8 @@ //! Provides CLI-specific Wasix components. -use anyhow::Error; use std::{sync::Arc, time::Duration}; +use anyhow::Error; use futures::future::BoxFuture; use indicatif::ProgressBar; use is_terminal::IsTerminal as _; @@ -113,9 +113,19 @@ impl wasmer_wasix::Runtime for Monitorin module: HashedModuleData, engine: Option<&Engine>, ) -> BoxFuture<'_, Result> { - let hash = *module.hash(); - let fut = self.runtime.load_hashed_module(module, engine); - Box::pin(compile_with_progress(fut, hash, None, self.quiet_mode)) + if self.quiet_mode { + Box::pin(self.runtime.load_hashed_module(module, engine)) + } else { + let hash = *module.hash(); + let fut = self.runtime.load_hashed_module(module, engine); + Box::pin(compile_with_progress( + &self.progress, + fut, + hash, + None, + self.quiet_mode, + )) + } } fn load_hashed_module_sync( @@ -123,43 +133,57 @@ impl wasmer_wasix::Runtime for Monitorin wasm: HashedModuleData, engine: Option<&Engine>, ) -> Result { - let hash = *wasm.hash(); - compile_with_progress_sync( - || self.runtime.load_hashed_module_sync(wasm, engine), - &hash, - None, - self.quiet_mode, - ) + if self.quiet_mode { + self.runtime.load_hashed_module_sync(wasm, engine) + } else { + let hash = *wasm.hash(); + compile_with_progress_sync( + &self.progress, + move || self.runtime.load_hashed_module_sync(wasm, engine), + &hash, + None, + ) + } } fn load_command_module( &self, cmd: &BinaryPackageCommand, ) -> BoxFuture<'_, Result> { - let fut = self.runtime.load_command_module(cmd); + if self.quiet_mode { + self.runtime.load_command_module(cmd) + } else { + let fut = self.runtime.load_command_module(cmd); - Box::pin(compile_with_progress( - fut, - *cmd.hash(), - Some(cmd.name().to_owned()), - self.quiet_mode, - )) + Box::pin(compile_with_progress( + &self.progress, + fut, + *cmd.hash(), + Some(cmd.name().to_owned()), + self.quiet_mode, + )) + } } fn load_command_module_sync( &self, cmd: &wasmer_wasix::bin_factory::BinaryPackageCommand, ) -> Result { - compile_with_progress_sync( - || self.runtime.load_command_module_sync(cmd), - cmd.hash(), - Some(cmd.name()), - self.quiet_mode, - ) + if self.quiet_mode { + self.runtime.load_command_module_sync(cmd) + } else { + compile_with_progress_sync( + &self.progress, + || self.runtime.load_command_module_sync(cmd), + cmd.hash(), + Some(cmd.name()), + ) + } } } async fn compile_with_progress<'a, F, T>( + bar: &ProgressBar, fut: F, hash: ModuleHash, name: Option, @@ -169,42 +193,55 @@ where F: std::future::Future + Send + 'a, T: Send + 'static, { - let mut pb = new_progressbar_compile(&hash, name.as_deref(), quiet_mode); - let res = fut.await; - pb.finish_and_clear(); - res + + + if quiet_mode { + fut.await + } else { + let should_clear = bar.is_finished() || bar.is_hidden(); + show_compile_progress(bar, &hash, name.as_deref()); + let res = fut.await; + if should_clear { + bar.finish_and_clear(); + } + + res + } } fn compile_with_progress_sync( + bar: &ProgressBar, f: F, hash: &ModuleHash, name: Option<&str>, - quiet_mode: bool, ) -> T where F: FnOnce() -> T, { - let mut pb = new_progressbar_compile(hash, name, quiet_mode); + let should_clear = bar.is_finished() || bar.is_hidden(); + show_compile_progress(bar, hash, name); let res = f(); - pb.finish_and_clear(); + if should_clear { + bar.finish_and_clear(); + } res } -fn new_progressbar_compile(hash: &ModuleHash, name: Option<&str>, quiet_mode: bool) -> ProgressBar { +fn show_compile_progress(bar: &ProgressBar, hash: &ModuleHash, name: Option<&str>) { // Only show a spinner if we're running in a TTY let hash = hash.to_string(); let hash = &hash[0..8]; - if !quiet_mode && std::io::stderr().is_terminal() { - let msg = if let Some(name) = name { - format!("Compiling WebAssembly module for command '{name}' ({hash})...") - } else { - format!("Compiling WebAssembly module {hash}...") - }; - let pb = ProgressBar::new_spinner().with_message(msg); - pb.enable_steady_tick(Duration::from_millis(100)); - pb + let msg = if let Some(name) = name { + format!("Compiling WebAssembly module for command '{name}' ({hash})...") } else { - ProgressBar::hidden() + format!("Compiling WebAssembly module {hash}...") + }; + + bar.set_message(msg); + bar.enable_steady_tick(Duration::from_millis(100)); + + if bar.is_finished() || bar.is_hidden() { + bar.reset(); } } diff --git a/lib/cli/src/logging.rs b/lib/cli/src/logging.rs index a76e0dc5d3e..bfe84e42f66 100644 --- a/lib/cli/src/logging.rs +++ b/lib/cli/src/logging.rs @@ -32,6 +32,11 @@ impl Output { self.verbose > 0 } + /// Returns true if either the `--quiet` flag is set or stderr is not a TTY. + pub fn is_quiet_or_no_tty(&self) -> bool { + self.quiet || !std::io::stderr().is_terminal() + } + /// Initialize logging based on the `$RUST_LOG` environment variable and /// command-line flags. pub fn initialize_logging(&self) { From a98b740a52a2926f299086b2fa65ed70de713f67 Mon Sep 17 00:00:00 2001 From: Christoph Herzog Date: Fri, 24 Oct 2025 06:10:51 +0200 Subject: [PATCH 3/3] chore(deps): Replace is-terminal crate with stdlib The functionality from the is-terminal crate was lifted into the standard library. Since we recently bumped the Rust MSRV, we can now rely on it and remove a dependency. --- Cargo.lock | 2 -- lib/cli-compiler/Cargo.toml | 1 - lib/cli-compiler/src/utils.rs | 2 +- lib/cli/Cargo.toml | 1 - lib/cli/src/commands/app/create.rs | 2 +- lib/cli/src/commands/app/delete.rs | 2 +- lib/cli/src/commands/app/deploy.rs | 2 +- lib/cli/src/commands/app/regions/list.rs | 2 +- lib/cli/src/commands/app/secrets/create.rs | 2 +- lib/cli/src/commands/app/secrets/delete.rs | 2 +- lib/cli/src/commands/app/secrets/list.rs | 2 +- lib/cli/src/commands/app/secrets/reveal.rs | 2 +- lib/cli/src/commands/app/secrets/update.rs | 2 +- lib/cli/src/commands/auth/logout.rs | 2 +- lib/cli/src/commands/mod.rs | 3 ++- lib/cli/src/commands/package/publish.rs | 2 +- lib/cli/src/commands/package/push.rs | 2 +- lib/cli/src/commands/package/tag.rs | 2 +- lib/cli/src/commands/run/mod.rs | 13 ++++++------- lib/cli/src/commands/run/runtime.rs | 4 +--- lib/cli/src/logging.rs | 2 +- 21 files changed, 24 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8565abfa0fb..8041027777c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6936,7 +6936,6 @@ dependencies = [ "indexmap 2.12.0", "indicatif", "interfaces", - "is-terminal", "libc", "log", "lzma-rs", @@ -7040,7 +7039,6 @@ dependencies = [ "colored 2.2.0", "distance", "fern", - "is-terminal", "log", "target-lexicon 0.13.3", "unix_mode", diff --git a/lib/cli-compiler/Cargo.toml b/lib/cli-compiler/Cargo.toml index dfc5c3de3de..680bb8e78db 100644 --- a/lib/cli-compiler/Cargo.toml +++ b/lib/cli-compiler/Cargo.toml @@ -24,7 +24,6 @@ wasmer-compiler = { version = "=6.1.0", path = "../compiler", features = [ "compiler", ] } wasmer-types = { version = "=6.1.0", path = "../types", features = ["detect-wasm-features"] } -is-terminal = "0.4.7" colored = "2.0" anyhow.workspace = true # For the function names autosuggestion diff --git a/lib/cli-compiler/src/utils.rs b/lib/cli-compiler/src/utils.rs index ee18e915a5a..25d881fbecc 100644 --- a/lib/cli-compiler/src/utils.rs +++ b/lib/cli-compiler/src/utils.rs @@ -1,6 +1,6 @@ //! Utility functions for the WebAssembly module use anyhow::{Context, Result, bail}; -use is_terminal::IsTerminal; +use std::io::IsTerminal as _; use std::path::PathBuf; use std::{env, path::Path}; diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml index 769848d09e9..bf745d90563 100644 --- a/lib/cli/Cargo.toml +++ b/lib/cli/Cargo.toml @@ -159,7 +159,6 @@ time01 = { package = "time", version = "0.1.45", optional = true } # Third-party dependencies. http.workspace = true -is-terminal = "0.4.7" colored = "2.0" anyhow.workspace = true bytesize.workspace = true diff --git a/lib/cli/src/commands/app/create.rs b/lib/cli/src/commands/app/create.rs index c52806489e1..82ddee1cde5 100644 --- a/lib/cli/src/commands/app/create.rs +++ b/lib/cli/src/commands/app/create.rs @@ -13,8 +13,8 @@ use colored::Colorize; use dialoguer::{Confirm, Select, theme::ColorfulTheme}; use futures::stream::TryStreamExt; use indexmap::IndexMap; -use is_terminal::IsTerminal; use path_clean::PathClean; +use std::io::IsTerminal as _; use wasmer_backend_api::{ WasmerClient, types::{AppTemplate, TemplateLanguage}, diff --git a/lib/cli/src/commands/app/delete.rs b/lib/cli/src/commands/app/delete.rs index 6ae4ca19dbc..4bcf49dd30e 100644 --- a/lib/cli/src/commands/app/delete.rs +++ b/lib/cli/src/commands/app/delete.rs @@ -1,7 +1,7 @@ //! Delete an Edge app. use dialoguer::Confirm; -use is_terminal::IsTerminal; +use std::io::IsTerminal as _; use super::util::AppIdentOpts; use crate::{commands::AsyncCliCommand, config::WasmerEnv}; diff --git a/lib/cli/src/commands/app/deploy.rs b/lib/cli/src/commands/app/deploy.rs index 74fb954849c..c43f5108981 100644 --- a/lib/cli/src/commands/app/deploy.rs +++ b/lib/cli/src/commands/app/deploy.rs @@ -14,7 +14,7 @@ use bytesize::ByteSize; use colored::Colorize; use dialoguer::{Confirm, theme::ColorfulTheme}; use indexmap::IndexMap; -use is_terminal::IsTerminal; +use std::io::IsTerminal as _; use std::io::Write; use std::{path::Path, path::PathBuf, str::FromStr, time::Duration}; use wasmer_backend_api::{ diff --git a/lib/cli/src/commands/app/regions/list.rs b/lib/cli/src/commands/app/regions/list.rs index 9828d24abb4..f0782fe1642 100644 --- a/lib/cli/src/commands/app/regions/list.rs +++ b/lib/cli/src/commands/app/regions/list.rs @@ -1,5 +1,5 @@ use crate::{commands::AsyncCliCommand, config::WasmerEnv, opts::ListFormatOpts}; -use is_terminal::IsTerminal; +use std::io::IsTerminal as _; /// List available Edge regions. #[derive(clap::Parser, Debug)] diff --git a/lib/cli/src/commands/app/secrets/create.rs b/lib/cli/src/commands/app/secrets/create.rs index 6f62594c9da..0719184f3ce 100644 --- a/lib/cli/src/commands/app/secrets/create.rs +++ b/lib/cli/src/commands/app/secrets/create.rs @@ -6,7 +6,7 @@ use crate::{ use anyhow::Context; use colored::Colorize; use dialoguer::theme::ColorfulTheme; -use is_terminal::IsTerminal; +use std::io::IsTerminal as _; use std::{ collections::{HashMap, HashSet}, path::{Path, PathBuf}, diff --git a/lib/cli/src/commands/app/secrets/delete.rs b/lib/cli/src/commands/app/secrets/delete.rs index a402424dbad..62333115a52 100644 --- a/lib/cli/src/commands/app/secrets/delete.rs +++ b/lib/cli/src/commands/app/secrets/delete.rs @@ -4,7 +4,7 @@ use crate::{ }; use colored::Colorize; use dialoguer::theme::ColorfulTheme; -use is_terminal::IsTerminal; +use std::io::IsTerminal as _; use std::path::{Path, PathBuf}; use wasmer_backend_api::WasmerClient; diff --git a/lib/cli/src/commands/app/secrets/list.rs b/lib/cli/src/commands/app/secrets/list.rs index 07a44c321d5..b1a92375e77 100644 --- a/lib/cli/src/commands/app/secrets/list.rs +++ b/lib/cli/src/commands/app/secrets/list.rs @@ -4,7 +4,7 @@ use crate::{ config::WasmerEnv, opts::ListFormatOpts, }; -use is_terminal::IsTerminal; +use std::io::IsTerminal as _; use std::path::PathBuf; /// Retrieve the value of an existing app secret. diff --git a/lib/cli/src/commands/app/secrets/reveal.rs b/lib/cli/src/commands/app/secrets/reveal.rs index e6738542a3f..781216dd1cb 100644 --- a/lib/cli/src/commands/app/secrets/reveal.rs +++ b/lib/cli/src/commands/app/secrets/reveal.rs @@ -6,7 +6,7 @@ use crate::{ utils::render::{ItemFormat, ListFormat}, }; use dialoguer::theme::ColorfulTheme; -use is_terminal::IsTerminal; +use std::io::IsTerminal as _; use std::path::PathBuf; /// Reveal the value of an existing app secret. diff --git a/lib/cli/src/commands/app/secrets/update.rs b/lib/cli/src/commands/app/secrets/update.rs index f55bfd459f9..7ead78ae2b2 100644 --- a/lib/cli/src/commands/app/secrets/update.rs +++ b/lib/cli/src/commands/app/secrets/update.rs @@ -6,7 +6,7 @@ use crate::{ use anyhow::Context; use colored::Colorize; use dialoguer::theme::ColorfulTheme; -use is_terminal::IsTerminal; +use std::io::IsTerminal as _; use std::{ collections::HashSet, path::{Path, PathBuf}, diff --git a/lib/cli/src/commands/auth/logout.rs b/lib/cli/src/commands/auth/logout.rs index 22b15eb4be1..b8934a6483d 100644 --- a/lib/cli/src/commands/auth/logout.rs +++ b/lib/cli/src/commands/auth/logout.rs @@ -3,7 +3,7 @@ use crate::{ config::{DEFAULT_PROD_REGISTRY, WasmerConfig, WasmerEnv}, }; use colored::Colorize; -use is_terminal::IsTerminal; +use std::io::IsTerminal as _; /// Log out from Wasmer #[derive(Debug, Clone, clap::Parser)] diff --git a/lib/cli/src/commands/mod.rs b/lib/cli/src/commands/mod.rs index 3df02b915ec..73969d7d732 100644 --- a/lib/cli/src/commands/mod.rs +++ b/lib/cli/src/commands/mod.rs @@ -32,6 +32,7 @@ mod validate; #[cfg(feature = "wast")] mod wast; use std::ffi::OsString; +use std::io::IsTerminal as _; use tokio::task::JoinHandle; #[cfg(target_os = "linux")] @@ -75,7 +76,7 @@ pub(crate) trait AsyncCliCommand: Send + Sync { &self, done: tokio::sync::oneshot::Receiver<()>, ) -> Option>> { - if is_terminal::IsTerminal::is_terminal(&std::io::stdin()) { + if std::io::stdin().is_terminal() { return Some(tokio::task::spawn(async move { tokio::select! { _ = done => {} diff --git a/lib/cli/src/commands/package/publish.rs b/lib/cli/src/commands/package/publish.rs index d26e45eb4b0..bafeee76e2d 100644 --- a/lib/cli/src/commands/package/publish.rs +++ b/lib/cli/src/commands/package/publish.rs @@ -10,7 +10,7 @@ use crate::{ config::WasmerEnv, }; use colored::Colorize; -use is_terminal::IsTerminal; +use std::io::IsTerminal as _; use std::path::{Path, PathBuf}; use wasmer_backend_api::WasmerClient; use wasmer_config::package::{Manifest, PackageIdent}; diff --git a/lib/cli/src/commands/package/push.rs b/lib/cli/src/commands/package/push.rs index 1b9c01e1ce8..831e60cb563 100644 --- a/lib/cli/src/commands/package/push.rs +++ b/lib/cli/src/commands/package/push.rs @@ -5,7 +5,7 @@ use crate::{ }; use anyhow::Context; use colored::Colorize; -use is_terminal::IsTerminal; +use std::io::IsTerminal as _; use std::path::{Path, PathBuf}; use wasmer_backend_api::WasmerClient; use wasmer_config::package::{Manifest, PackageHash}; diff --git a/lib/cli/src/commands/package/tag.rs b/lib/cli/src/commands/package/tag.rs index 29bb49a78cb..fb2c44d4367 100644 --- a/lib/cli/src/commands/package/tag.rs +++ b/lib/cli/src/commands/package/tag.rs @@ -8,7 +8,7 @@ use crate::{ use anyhow::Context; use colored::Colorize; use dialoguer::{Confirm, theme::ColorfulTheme}; -use is_terminal::IsTerminal; +use std::io::IsTerminal as _; use std::{ path::{Path, PathBuf}, str::FromStr, diff --git a/lib/cli/src/commands/run/mod.rs b/lib/cli/src/commands/run/mod.rs index 51c5223c05a..881681a8967 100644 --- a/lib/cli/src/commands/run/mod.rs +++ b/lib/cli/src/commands/run/mod.rs @@ -305,13 +305,12 @@ impl Run { preferred_webc_version, )?; - let new_runtime = Arc::new(MonitoringRuntime::new( - new_runtime, - pb.clone(), - output.is_quiet_or_no_tty(), - )); - return self.execute_webc(&pkg, new_runtime); - } + let new_runtime = Arc::new(MonitoringRuntime::new( + new_runtime, + pb.clone(), + output.is_quiet_or_no_tty(), + )); + return self.execute_webc(&pkg, new_runtime); } } } diff --git a/lib/cli/src/commands/run/runtime.rs b/lib/cli/src/commands/run/runtime.rs index 638a38787fa..d0e712b6e06 100644 --- a/lib/cli/src/commands/run/runtime.rs +++ b/lib/cli/src/commands/run/runtime.rs @@ -5,7 +5,7 @@ use std::{sync::Arc, time::Duration}; use anyhow::Error; use futures::future::BoxFuture; use indicatif::ProgressBar; -use is_terminal::IsTerminal as _; +use std::io::IsTerminal as _; use wasmer::{Engine, Module}; use wasmer_config::package::PackageSource; use wasmer_types::ModuleHash; @@ -193,8 +193,6 @@ where F: std::future::Future + Send + 'a, T: Send + 'static, { - - if quiet_mode { fut.await } else { diff --git a/lib/cli/src/logging.rs b/lib/cli/src/logging.rs index bfe84e42f66..2bce3231f09 100644 --- a/lib/cli/src/logging.rs +++ b/lib/cli/src/logging.rs @@ -1,6 +1,6 @@ //! Logging functions for the debug feature. -use is_terminal::IsTerminal; +use std::io::IsTerminal as _; use tracing::level_filters::LevelFilter; use tracing_subscriber::{EnvFilter, fmt, layer::SubscriberExt, util::SubscriberInitExt};