From 6be1686bcb44ed1c681a0335204c7f145d09a84e Mon Sep 17 00:00:00 2001 From: Michael-F-Bryan Date: Tue, 20 Jun 2023 19:35:50 +0800 Subject: [PATCH 1/3] Added a WasmerDir abstraction --- lib/cli/src/commands/add.rs | 28 ++---- lib/cli/src/commands/config.rs | 46 +++------- lib/cli/src/commands/init.rs | 11 ++- lib/cli/src/commands/login.rs | 148 +++++++++++++++++++------------ lib/cli/src/commands/publish.rs | 30 +++---- lib/cli/src/commands/run.rs | 18 ++-- lib/cli/src/commands/run/wasi.rs | 30 +++---- lib/cli/src/commands/whoami.rs | 13 ++- lib/cli/src/lib.rs | 3 + lib/cli/src/wasmer_dir.rs | 125 ++++++++++++++++++++++++++ 10 files changed, 287 insertions(+), 165 deletions(-) create mode 100644 lib/cli/src/wasmer_dir.rs diff --git a/lib/cli/src/commands/add.rs b/lib/cli/src/commands/add.rs index 04f6038e143..d6960a5f73d 100644 --- a/lib/cli/src/commands/add.rs +++ b/lib/cli/src/commands/add.rs @@ -2,14 +2,15 @@ use std::process::{Command, Stdio}; use anyhow::{Context, Error}; use clap::Parser; -use wasmer_registry::{Bindings, ProgrammingLanguage, WasmerConfig}; +use wasmer_registry::{Bindings, ProgrammingLanguage}; + +use crate::WasmerDir; /// Add a Wasmer package's bindings to your application. #[derive(Debug, Parser)] pub struct Add { - /// The registry to fetch bindings from. - #[clap(long, env = "WASMER_REGISTRY")] - registry: Option, + #[clap(flatten)] + wasmer_dir: WasmerDir, /// Add the JavaScript bindings using "npm install". #[clap(long, groups = &["bindings", "js"])] npm: bool, @@ -32,10 +33,11 @@ impl Add { anyhow::ensure!(!self.packages.is_empty(), "No packages specified"); let registry = self - .registry() + .wasmer_dir + .registry_endpoint() .context("Unable to determine which registry to use")?; - let bindings = self.lookup_bindings(®istry)?; + let bindings = self.lookup_bindings(registry.as_str())?; let mut cmd = self.target()?.command(&bindings)?; cmd.stdin(Stdio::null()) @@ -71,20 +73,6 @@ impl Add { Ok(bindings_to_add) } - fn registry(&self) -> Result { - match &self.registry { - Some(r) => Ok(r.clone()), - None => { - let wasmer_dir = - WasmerConfig::get_wasmer_dir().map_err(|e| anyhow::anyhow!("{e}"))?; - let cfg = WasmerConfig::from_file(&wasmer_dir) - .map_err(Error::msg) - .context("Unable to load Wasmer config file")?; - Ok(cfg.registry.get_current_registry()) - } - } - } - fn target(&self) -> Result { match (self.pip, self.npm, self.yarn) { (false, false, false) => Err(anyhow::anyhow!( diff --git a/lib/cli/src/commands/config.rs b/lib/cli/src/commands/config.rs index 0de850a6839..2c4ae8ae402 100644 --- a/lib/cli/src/commands/config.rs +++ b/lib/cli/src/commands/config.rs @@ -1,14 +1,15 @@ -use crate::VERSION; +use crate::{WasmerDir, VERSION}; use anyhow::{Context, Result}; use clap::Parser; -use std::env; -use std::path::PathBuf; use std::str::ParseBoolError; use wasmer_registry::WasmerConfig; #[derive(Debug, Parser)] /// The options for the `wasmer config` subcommand: `wasmer config get --OPTION` or `wasmer config set [FLAG]` pub struct Config { + #[clap(flatten)] + wasmer_dir: WasmerDir, + #[clap(flatten)] flags: Flags, /// Subcommand for `wasmer config get | set` @@ -168,29 +169,12 @@ impl Config { fn inner_execute(&self) -> Result<()> { if let Some(s) = self.set.as_ref() { - return s.execute(); + return s.execute(&self.wasmer_dir); } let flags = &self.flags; - let key = "WASMER_DIR"; - let wasmer_dir = env::var(key) - .ok() - .or_else(|| option_env!("WASMER_INSTALL_PREFIX").map(str::to_string)) - .or_else(|| { - // Allowing deprecated function home_dir since it works fine, - // and will never be removed from std. - #[allow(deprecated)] - let dir = std::env::home_dir()?.join(".wasmer").to_str()?.to_string(); - - Some(dir) - }) - .context(format!( - "failed to retrieve the {} environment variables", - key - ))?; - - let prefix = PathBuf::from(wasmer_dir); + let prefix = self.wasmer_dir.dir(); let prefixdir = prefix.display().to_string(); let bindir = prefix.join("bin").display().to_string(); @@ -233,9 +217,7 @@ impl Config { } if flags.config_path { - let wasmer_dir = WasmerConfig::get_wasmer_dir() - .map_err(|e| anyhow::anyhow!("could not find wasmer dir: {e}"))?; - let path = WasmerConfig::get_file_location(&wasmer_dir); + let path = WasmerConfig::get_file_location(self.wasmer_dir.dir()); println!("{}", path.display()); } @@ -244,16 +226,10 @@ impl Config { } impl GetOrSet { - fn execute(&self) -> Result<()> { - let wasmer_dir = WasmerConfig::get_wasmer_dir() - .map_err(|e| anyhow::anyhow!("could not find wasmer dir: {e}"))?; - let config_file = WasmerConfig::get_file_location(&wasmer_dir); - let mut config = WasmerConfig::from_file(&wasmer_dir).map_err(|e| { - anyhow::anyhow!( - "could not find config file {e} at {}", - config_file.display() - ) - })?; + fn execute(&self, wasmer_dir: &WasmerDir) -> Result<()> { + let config_file = WasmerConfig::get_file_location(wasmer_dir.dir()); + let mut config = wasmer_dir.config()?; + match self { GetOrSet::Get(g) => match g { RetrievableConfigField::RegistryUrl => { diff --git a/lib/cli/src/commands/init.rs b/lib/cli/src/commands/init.rs index 5b7586f9495..fff6c701d72 100644 --- a/lib/cli/src/commands/init.rs +++ b/lib/cli/src/commands/init.rs @@ -5,7 +5,8 @@ use indexmap::IndexMap; use std::collections::HashMap; use std::path::Path; use std::path::PathBuf; -use wasmer_registry::WasmerConfig; + +use crate::WasmerDir; static NOTE: &str = "# See more keys and definitions at https://docs.wasmer.io/registry/manifest"; @@ -14,6 +15,9 @@ const NEWLINE: &str = if cfg!(windows) { "\r\n" } else { "\n" }; /// CLI args for the `wasmer init` command #[derive(Debug, Parser)] pub struct Init { + #[clap(flatten)] + wasmer_dir: WasmerDir, + /// Initialize wasmer.toml for a library package #[clap(long, group = "crate-type")] pub lib: bool, @@ -136,6 +140,7 @@ impl Init { self.template.as_ref(), self.include.as_slice(), self.quiet, + self.wasmer_dir.dir(), )?; if let Some(parent) = target_file.parent() { @@ -347,6 +352,7 @@ fn construct_manifest( template: Option<&Template>, include_fs: &[String], quiet: bool, + wasmer_dir: &Path, ) -> Result { if let Some(ct) = cargo_toml.as_ref() { let msg = format!( @@ -365,9 +371,8 @@ fn construct_manifest( .map(|p| &p.name) .unwrap_or(fallback_package_name) }); - let wasmer_dir = WasmerConfig::get_wasmer_dir().map_err(|e| anyhow::anyhow!("{e}"))?; let namespace = namespace.or_else(|| { - wasmer_registry::whoami(&wasmer_dir, None, None) + wasmer_registry::whoami(wasmer_dir, None, None) .ok() .map(|o| o.1) }); diff --git a/lib/cli/src/commands/login.rs b/lib/cli/src/commands/login.rs index 06a90d9b315..2f7c4bea197 100644 --- a/lib/cli/src/commands/login.rs +++ b/lib/cli/src/commands/login.rs @@ -1,86 +1,122 @@ +use std::path::PathBuf; + use clap::Parser; #[cfg(not(test))] use dialoguer::Input; -use wasmer_registry::WasmerConfig; + +use crate::{Registry, WasmerDir}; /// Subcommand for listing packages #[derive(Debug, Clone, Parser)] pub struct Login { - /// Registry to log into (default: wasmer.io) - #[clap(long, default_value = "wasmer.io")] - pub registry: String, - /// Login token - #[clap(name = "TOKEN")] + /// Set Wasmer's home directory + #[clap(long, env = "WASMER_DIR", default_value = crate::WASMER_DIR.as_os_str())] + pub wasmer_dir: PathBuf, + /// The registry to fetch packages from (inferred from the environment by + /// default) + #[clap(long, env = "WASMER_REGISTRY")] + pub registry: Option, + /// The API token to use when communicating with the registry (inferred from + /// the environment by default) pub token: Option, } impl Login { - fn get_token_or_ask_user(&self) -> Result { - match self.token.as_ref() { - Some(s) => Ok(s.clone()), - None => { - let registry_host = wasmer_registry::format_graphql(&self.registry); - let registry_tld = tldextract::TldExtractor::new(tldextract::TldOption::default()) - .extract(®istry_host) - .map_err(|e| { - std::io::Error::new( - std::io::ErrorKind::Other, - format!("Invalid registry for login {}: {e}", self.registry), - ) - })?; - let login_prompt = match ( - registry_tld.domain.as_deref(), - registry_tld.suffix.as_deref(), - ) { - (Some(d), Some(s)) => { - format!("Please paste the login token from https://{d}.{s}/settings/access-tokens") - } - _ => "Please paste the login token".to_string(), - }; - #[cfg(test)] - { - Ok(login_prompt) - } - #[cfg(not(test))] - { - Input::new().with_prompt(&login_prompt).interact_text() - } + fn get_token_or_ask_user(&self, wasmer_dir: &WasmerDir) -> Result { + if let Some(token) = &self.token { + return Ok(token.clone()); + } + + let registry_host = wasmer_dir.registry_endpoint()?; + let registry_tld = tldextract::TldExtractor::new(tldextract::TldOption::default()) + .extract(registry_host.as_str()) + .map_err(|e| { + std::io::Error::new( + std::io::ErrorKind::Other, + format!("Invalid registry for login {}: {e}", registry_host), + ) + })?; + let login_prompt = match ( + registry_tld.domain.as_deref(), + registry_tld.suffix.as_deref(), + ) { + (Some(d), Some(s)) => { + format!("Please paste the login token from https://{d}.{s}/settings/access-tokens") } + _ => "Please paste the login token".to_string(), + }; + #[cfg(test)] + { + Ok(login_prompt) + } + #[cfg(not(test))] + { + let token = Input::new().with_prompt(&login_prompt).interact_text()?; + Ok(token) } } + fn wasmer_dir(&self) -> WasmerDir { + WasmerDir::new( + self.wasmer_dir.clone(), + self.registry.clone(), + self.token.clone(), + ) + } + /// execute [List] pub fn execute(&self) -> Result<(), anyhow::Error> { - let token = self.get_token_or_ask_user()?; - let wasmer_dir = - WasmerConfig::get_wasmer_dir().map_err(|e| anyhow::anyhow!("no wasmer dir: {e}"))?; - match wasmer_registry::login::login_and_save_token(&wasmer_dir, &self.registry, &token)? { + let wasmer_dir = self.wasmer_dir(); + let token = self.get_token_or_ask_user(&wasmer_dir)?; + + let registry = wasmer_dir.registry_endpoint()?; + match wasmer_registry::login::login_and_save_token( + wasmer_dir.dir(), + registry.as_str(), + &token, + )? { Some(s) => println!("Login for Wasmer user {:?} saved", s), None => println!( "Error: no user found on registry {:?} with token {:?}. Token saved regardless.", - self.registry, token + registry, token ), } Ok(()) } } -#[test] -fn test_login_2() { - let login = Login { - registry: "wasmer.wtf".to_string(), - token: None, - }; +#[cfg(test)] +mod tests { + use tempfile::TempDir; + + use super::*; - assert_eq!( - login.get_token_or_ask_user().unwrap(), - "Please paste the login token from https://wasmer.wtf/settings/access-tokens" - ); + #[test] + fn interactive_login() { + let temp = TempDir::new().unwrap(); + let login = Login { + registry: Some("wasmer.wtf".into()), + wasmer_dir: temp.path().to_path_buf(), + token: None, + }; + let wasmer_dir = login.wasmer_dir(); - let login = Login { - registry: "wasmer.wtf".to_string(), - token: Some("abc".to_string()), - }; + assert_eq!( + login.get_token_or_ask_user(&wasmer_dir).unwrap(), + "Please paste the login token from https://wasmer.wtf/settings/access-tokens" + ); + } + + #[test] + fn login_with_token() { + let temp = TempDir::new().unwrap(); + let login = Login { + registry: Some("wasmer.wtf".into()), + wasmer_dir: temp.path().to_path_buf(), + token: Some("abc".to_string()), + }; + let wasmer_dir = login.wasmer_dir(); - assert_eq!(login.get_token_or_ask_user().unwrap(), "abc"); + assert_eq!(login.get_token_or_ask_user(&wasmer_dir).unwrap(), "abc"); + } } diff --git a/lib/cli/src/commands/publish.rs b/lib/cli/src/commands/publish.rs index bd332d6276c..5ceb1eec26f 100644 --- a/lib/cli/src/commands/publish.rs +++ b/lib/cli/src/commands/publish.rs @@ -1,14 +1,15 @@ -use anyhow::Context; +use std::path::Path; + use clap::Parser; -use wasmer_registry::WasmerConfig; use wasmer_wasix::runtime::resolver::WapmSource; +use crate::WasmerDir; + /// Publish a package to the package registry. #[derive(Debug, Parser)] pub struct Publish { - /// Registry to publish to - #[clap(long)] - pub registry: Option, + #[clap(flatten)] + wasmer_dir: WasmerDir, /// Run the publish logic without sending anything to the registry server #[clap(long, name = "dry-run")] pub dry_run: bool, @@ -21,9 +22,6 @@ pub struct Publish { /// Override the package version of the uploaded package in the wasmer.toml #[clap(long)] pub version: Option, - /// Override the token (by default, it will use the current logged in user) - #[clap(long)] - pub token: Option, /// Skip validation of the uploaded package #[clap(long)] pub no_validate: bool, @@ -38,18 +36,22 @@ impl Publish { /// Executes `wasmer publish` pub fn execute(&self) -> Result<(), anyhow::Error> { let publish = wasmer_registry::package::builder::Publish { - registry: self.registry.clone(), + registry: self + .wasmer_dir + .registry_endpoint() + .map(|u| u.to_string()) + .ok(), dry_run: self.dry_run, quiet: self.quiet, package_name: self.package_name.clone(), version: self.version.clone(), - token: self.token.clone(), + token: self.wasmer_dir.token(), no_validate: self.no_validate, package_path: self.package_path.clone(), }; publish.execute().map_err(on_error)?; - if let Err(e) = invalidate_graphql_query_cache() { + if let Err(e) = invalidate_graphql_query_cache(self.wasmer_dir.dir()) { tracing::warn!( error = &*e, "Unable to invalidate the cache used for package version queries", @@ -72,11 +74,7 @@ fn on_error(e: anyhow::Error) -> anyhow::Error { // are cleaner ways to achieve this, but for now we're just going to // clear out the whole GraphQL query cache. // See https://github.com/wasmerio/wasmer/pull/3983 for more -fn invalidate_graphql_query_cache() -> Result<(), anyhow::Error> { - let wasmer_dir = WasmerConfig::get_wasmer_dir() - .map_err(anyhow::Error::msg) - .context("Unable to determine the wasmer dir")?; - +fn invalidate_graphql_query_cache(wasmer_dir: &Path) -> Result<(), anyhow::Error> { WapmSource::invalidate_local_cache(wasmer_dir)?; Ok(()) diff --git a/lib/cli/src/commands/run.rs b/lib/cli/src/commands/run.rs index 82d0b17ff65..502ce4bdfbc 100644 --- a/lib/cli/src/commands/run.rs +++ b/lib/cli/src/commands/run.rs @@ -49,23 +49,17 @@ use wasmer_wasix::{ }; use webc::{metadata::Manifest, Container}; -use crate::{commands::run::wasi::Wasi, error::PrettyError, logging::Output, store::StoreOptions}; +use crate::{ + commands::run::wasi::Wasi, error::PrettyError, logging::Output, store::StoreOptions, WasmerDir, +}; const TICK: Duration = Duration::from_millis(250); -static WASMER_HOME: Lazy = Lazy::new(|| { - wasmer_registry::WasmerConfig::get_wasmer_dir() - .ok() - .or_else(|| dirs::home_dir().map(|home| home.join(".wasmer"))) - .unwrap_or_else(|| PathBuf::from(".wasmer")) -}); - /// The unstable `wasmer run` subcommand. #[derive(Debug, Parser)] pub struct Run { - /// The Wasmer home directory. - #[clap(long = "wasmer-dir", env = "WASMER_DIR", default_value = WASMER_HOME.as_os_str())] - wasmer_dir: PathBuf, + #[clap(flatten)] + wasmer_dir: WasmerDir, #[clap(flatten)] store: StoreOptions, #[clap(flatten)] @@ -358,7 +352,7 @@ impl Run { }; let store = StoreOptions::default(); Ok(Run { - wasmer_dir: WASMER_HOME.clone(), + wasmer_dir: WasmerDir::default(), store, wasi: Wasi::for_binfmt_interpreter()?, wcgi: WcgiOptions::default(), diff --git a/lib/cli/src/commands/run/wasi.rs b/lib/cli/src/commands/run/wasi.rs index 273329926b1..d5a03da1a1a 100644 --- a/lib/cli/src/commands/run/wasi.rs +++ b/lib/cli/src/commands/run/wasi.rs @@ -35,7 +35,10 @@ use wasmer_wasix::{ WasiVersion, }; -use crate::utils::{parse_envvar, parse_mapdir}; +use crate::{ + utils::{parse_envvar, parse_mapdir}, + WasmerDir, +}; const WAPM_SOURCE_CACHE_TIMEOUT: Duration = Duration::from_secs(10 * 60); @@ -110,10 +113,6 @@ pub struct Wasi { /// Require WASI modules to only import 1 version of WASI. #[clap(long = "deny-multiple-wasi-versions")] pub deny_multiple_wasi_versions: bool, - - /// The registry to use. - #[clap(long, env = "WASMER_REGISTRY", value_parser = parse_registry)] - pub registry: Option, } pub struct RunProperties { @@ -249,7 +248,7 @@ impl Wasi { pub fn prepare_runtime( &self, engine: Engine, - wasmer_dir: &Path, + wasmer_dir: &WasmerDir, handle: Handle, ) -> Result { let mut rt = PluggableRuntime::new(Arc::new(TokioTaskManager::new(handle))); @@ -271,12 +270,12 @@ impl Wasi { let client = Arc::new(client); let package_loader = self - .prepare_package_loader(wasmer_dir, client.clone()) + .prepare_package_loader(wasmer_dir.dir(), client.clone()) .context("Unable to prepare the package loader")?; let registry = self.prepare_source(wasmer_dir, client)?; - let cache_dir = FileSystemCache::default_cache_dir(wasmer_dir); + let cache_dir = FileSystemCache::default_cache_dir(wasmer_dir.dir()); let module_cache = wasmer_wasix::runtime::module_cache::in_memory() .with_fallback(FileSystemCache::new(cache_dir)); @@ -328,7 +327,7 @@ impl Wasi { fn prepare_source( &self, - wasmer_dir: &Path, + wasmer_dir: &WasmerDir, client: Arc, ) -> Result { let mut source = MultiSource::new(); @@ -344,12 +343,12 @@ impl Wasi { source.add_source(preloaded); let graphql_endpoint = self.graphql_endpoint(wasmer_dir)?; - let cache_dir = WapmSource::default_cache_dir(wasmer_dir); + let cache_dir = WapmSource::default_cache_dir(wasmer_dir.dir()); let wapm_source = WapmSource::new(graphql_endpoint, Arc::clone(&client)) .with_local_cache(cache_dir, WAPM_SOURCE_CACHE_TIMEOUT); source.add_source(wapm_source); - let cache_dir = WebSource::default_cache_dir(wasmer_dir); + let cache_dir = WebSource::default_cache_dir(wasmer_dir.dir()); source.add_source(WebSource::new(cache_dir, client)); source.add_source(FileSystemSource::default()); @@ -357,13 +356,12 @@ impl Wasi { Ok(source) } - fn graphql_endpoint(&self, wasmer_dir: &Path) -> Result { - if let Some(endpoint) = &self.registry { - return Ok(endpoint.clone()); + fn graphql_endpoint(&self, wasmer_dir: &WasmerDir) -> Result { + if let Ok(endpoint) = wasmer_dir.registry_endpoint() { + return Ok(endpoint); } - let config = - wasmer_registry::WasmerConfig::from_file(wasmer_dir).map_err(anyhow::Error::msg)?; + let config = wasmer_dir.config()?; let graphql_endpoint = config.registry.get_graphql_url(); let graphql_endpoint = graphql_endpoint .parse() diff --git a/lib/cli/src/commands/whoami.rs b/lib/cli/src/commands/whoami.rs index 8d5b27fedee..adab954d0fb 100644 --- a/lib/cli/src/commands/whoami.rs +++ b/lib/cli/src/commands/whoami.rs @@ -1,21 +1,20 @@ use clap::Parser; -use wasmer_registry::WasmerConfig; + +use crate::WasmerDir; #[derive(Debug, Parser)] /// The options for the `wasmer whoami` subcommand pub struct Whoami { - /// Which registry to check the logged in username for - #[clap(long, name = "registry")] - pub registry: Option, + #[clap(flatten)] + wasmer_dir: WasmerDir, } impl Whoami { /// Execute `wasmer whoami` pub fn execute(&self) -> Result<(), anyhow::Error> { - let wasmer_dir = - WasmerConfig::get_wasmer_dir().map_err(|e| anyhow::anyhow!("no wasmer dir: {e}"))?; + let registry = self.wasmer_dir.registry_endpoint()?; let (registry, username) = - wasmer_registry::whoami(&wasmer_dir, self.registry.as_deref(), None)?; + wasmer_registry::whoami(self.wasmer_dir.dir(), Some(registry.as_str()), None)?; println!("logged into registry {registry:?} as user {username:?}"); Ok(()) } diff --git a/lib/cli/src/lib.rs b/lib/cli/src/lib.rs index 5e9d4597aad..5e0a5cae53c 100644 --- a/lib/cli/src/lib.rs +++ b/lib/cli/src/lib.rs @@ -27,6 +27,9 @@ pub mod package_source; pub mod store; pub mod suggestions; pub mod utils; +mod wasmer_dir; /// Version number of this crate. pub const VERSION: &str = env!("CARGO_PKG_VERSION"); + +pub use crate::wasmer_dir::{Registry, WasmerDir, WASMER_DIR}; diff --git a/lib/cli/src/wasmer_dir.rs b/lib/cli/src/wasmer_dir.rs new file mode 100644 index 00000000000..cdd3b9fbf9d --- /dev/null +++ b/lib/cli/src/wasmer_dir.rs @@ -0,0 +1,125 @@ +use std::path::{Path, PathBuf}; + +use anyhow::{Context, Error}; +use once_cell::sync::Lazy; +use url::Url; +use wasmer_registry::WasmerConfig; + +/// Command-line flags for determining `$WASMER_DIR` and interactions with the +/// registry. +#[derive(Debug, Clone, PartialEq, clap::Parser)] +pub struct WasmerDir { + /// Set Wasmer's home directory + #[clap(long, env = "WASMER_DIR", default_value = WASMER_DIR.as_os_str())] + wasmer_dir: PathBuf, + /// The registry to fetch packages from (inferred from the environment by + /// default) + #[clap(long, env = "WASMER_REGISTRY")] + registry: Option, + /// The API token to use when communicating with the registry (inferred from + /// the environment by default) + #[clap(long, env = "WASMER_TOKEN")] + token: Option, +} + +impl WasmerDir { + pub(crate) fn new( + wasmer_dir: PathBuf, + registry: Option, + token: Option, + ) -> Self { + WasmerDir { + wasmer_dir, + registry, + token, + } + } + + /// Get the GraphQL endpoint used to query the registry. + pub fn registry_endpoint(&self) -> Result { + if let Some(registry) = &self.registry { + return registry.graphql_endpoint(); + } + + let config = self.config()?; + let url = config.registry.get_current_registry().parse()?; + + Ok(url) + } + + /// Load the current Wasmer config. + pub fn config(&self) -> Result { + WasmerConfig::from_file(self.dir()) + .map_err(Error::msg) + .with_context(|| { + format!( + "Unable to load the config from the \"{}\" directory", + self.dir().display() + ) + }) + } + + /// The directory all Wasmer artifacts are stored in. + pub fn dir(&self) -> &Path { + &self.wasmer_dir + } + + /// The API token for the active registry. + pub fn token(&self) -> Option { + let config = self.config().ok()?; + let login = config.registry.current_login()?; + Some(login.token.clone()) + } +} + +impl Default for WasmerDir { + fn default() -> Self { + Self { + wasmer_dir: WASMER_DIR.clone(), + registry: None, + token: None, + } + } +} + +/// The default value for `$WASMER_DIR`. +pub static WASMER_DIR: Lazy = + Lazy::new(|| match wasmer_registry::WasmerConfig::get_wasmer_dir() { + Ok(path) => path, + Err(e) => { + if let Some(install_prefix) = std::env::var_os("WASMER_INSTALL_PREFIX") { + PathBuf::from(install_prefix) + } else { + panic!("Unable to determine the wasmer dir: {e}"); + } + } + }); + +/// A registry as specified by the user. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Registry(String); + +impl Registry { + /// Get the [`Registry`]'s string representation. + pub fn as_str(&self) -> &str { + self.0.as_str() + } + + /// Get the GraphQL endpoint for this [`Registry`]. + pub fn graphql_endpoint(&self) -> Result { + let url = wasmer_registry::format_graphql(self.as_str()).parse()?; + Ok(url) + } +} + +impl From for Registry { + fn from(value: String) -> Self { + Registry(value) + } +} + +impl From<&str> for Registry { + fn from(value: &str) -> Self { + Registry(value.to_string()) + } +} From 71072931409fc065349ff4adb2f84bd968a0ccdd Mon Sep 17 00:00:00 2001 From: Michael-F-Bryan Date: Tue, 20 Jun 2023 21:55:36 +0800 Subject: [PATCH 2/3] Rename WasmerDir to WasmerEnv --- lib/cli/src/commands/add.rs | 6 +- lib/cli/src/commands/config.rs | 16 ++--- lib/cli/src/commands/init.rs | 6 +- lib/cli/src/commands/login.rs | 36 +++++----- lib/cli/src/commands/publish.rs | 14 ++-- lib/cli/src/commands/run.rs | 12 ++-- lib/cli/src/commands/run/wasi.rs | 24 +++---- lib/cli/src/commands/whoami.rs | 8 +-- lib/cli/src/lib.rs | 4 +- lib/cli/src/{wasmer_dir.rs => wasmer_env.rs} | 14 ++-- tests/integration/cli/tests/config.rs | 69 ++++++++------------ 11 files changed, 98 insertions(+), 111 deletions(-) rename lib/cli/src/{wasmer_dir.rs => wasmer_env.rs} (91%) diff --git a/lib/cli/src/commands/add.rs b/lib/cli/src/commands/add.rs index d6960a5f73d..f21a4a1423f 100644 --- a/lib/cli/src/commands/add.rs +++ b/lib/cli/src/commands/add.rs @@ -4,13 +4,13 @@ use anyhow::{Context, Error}; use clap::Parser; use wasmer_registry::{Bindings, ProgrammingLanguage}; -use crate::WasmerDir; +use crate::WasmerEnv; /// Add a Wasmer package's bindings to your application. #[derive(Debug, Parser)] pub struct Add { #[clap(flatten)] - wasmer_dir: WasmerDir, + env: WasmerEnv, /// Add the JavaScript bindings using "npm install". #[clap(long, groups = &["bindings", "js"])] npm: bool, @@ -33,7 +33,7 @@ impl Add { anyhow::ensure!(!self.packages.is_empty(), "No packages specified"); let registry = self - .wasmer_dir + .env .registry_endpoint() .context("Unable to determine which registry to use")?; diff --git a/lib/cli/src/commands/config.rs b/lib/cli/src/commands/config.rs index 2c4ae8ae402..85934f1dcdc 100644 --- a/lib/cli/src/commands/config.rs +++ b/lib/cli/src/commands/config.rs @@ -1,4 +1,4 @@ -use crate::{WasmerDir, VERSION}; +use crate::{WasmerEnv, VERSION}; use anyhow::{Context, Result}; use clap::Parser; use std::str::ParseBoolError; @@ -8,7 +8,7 @@ use wasmer_registry::WasmerConfig; /// The options for the `wasmer config` subcommand: `wasmer config get --OPTION` or `wasmer config set [FLAG]` pub struct Config { #[clap(flatten)] - wasmer_dir: WasmerDir, + env: WasmerEnv, #[clap(flatten)] flags: Flags, @@ -169,12 +169,12 @@ impl Config { fn inner_execute(&self) -> Result<()> { if let Some(s) = self.set.as_ref() { - return s.execute(&self.wasmer_dir); + return s.execute(&self.env); } let flags = &self.flags; - let prefix = self.wasmer_dir.dir(); + let prefix = self.env.dir(); let prefixdir = prefix.display().to_string(); let bindir = prefix.join("bin").display().to_string(); @@ -217,7 +217,7 @@ impl Config { } if flags.config_path { - let path = WasmerConfig::get_file_location(self.wasmer_dir.dir()); + let path = WasmerConfig::get_file_location(self.env.dir()); println!("{}", path.display()); } @@ -226,9 +226,9 @@ impl Config { } impl GetOrSet { - fn execute(&self, wasmer_dir: &WasmerDir) -> Result<()> { - let config_file = WasmerConfig::get_file_location(wasmer_dir.dir()); - let mut config = wasmer_dir.config()?; + fn execute(&self, env: &WasmerEnv) -> Result<()> { + let config_file = WasmerConfig::get_file_location(env.dir()); + let mut config = env.config()?; match self { GetOrSet::Get(g) => match g { diff --git a/lib/cli/src/commands/init.rs b/lib/cli/src/commands/init.rs index fff6c701d72..a69f53e93f4 100644 --- a/lib/cli/src/commands/init.rs +++ b/lib/cli/src/commands/init.rs @@ -6,7 +6,7 @@ use std::collections::HashMap; use std::path::Path; use std::path::PathBuf; -use crate::WasmerDir; +use crate::WasmerEnv; static NOTE: &str = "# See more keys and definitions at https://docs.wasmer.io/registry/manifest"; @@ -16,7 +16,7 @@ const NEWLINE: &str = if cfg!(windows) { "\r\n" } else { "\n" }; #[derive(Debug, Parser)] pub struct Init { #[clap(flatten)] - wasmer_dir: WasmerDir, + env: WasmerEnv, /// Initialize wasmer.toml for a library package #[clap(long, group = "crate-type")] @@ -140,7 +140,7 @@ impl Init { self.template.as_ref(), self.include.as_slice(), self.quiet, - self.wasmer_dir.dir(), + self.env.dir(), )?; if let Some(parent) = target_file.parent() { diff --git a/lib/cli/src/commands/login.rs b/lib/cli/src/commands/login.rs index 2f7c4bea197..9ffe9aca3f9 100644 --- a/lib/cli/src/commands/login.rs +++ b/lib/cli/src/commands/login.rs @@ -4,7 +4,7 @@ use clap::Parser; #[cfg(not(test))] use dialoguer::Input; -use crate::{Registry, WasmerDir}; +use crate::{Registry, WasmerEnv}; /// Subcommand for listing packages #[derive(Debug, Clone, Parser)] @@ -22,12 +22,12 @@ pub struct Login { } impl Login { - fn get_token_or_ask_user(&self, wasmer_dir: &WasmerDir) -> Result { + fn get_token_or_ask_user(&self, env: &WasmerEnv) -> Result { if let Some(token) = &self.token { return Ok(token.clone()); } - let registry_host = wasmer_dir.registry_endpoint()?; + let registry_host = env.registry_endpoint()?; let registry_tld = tldextract::TldExtractor::new(tldextract::TldOption::default()) .extract(registry_host.as_str()) .map_err(|e| { @@ -56,8 +56,8 @@ impl Login { } } - fn wasmer_dir(&self) -> WasmerDir { - WasmerDir::new( + fn wasmer_env(&self) -> WasmerEnv { + WasmerEnv::new( self.wasmer_dir.clone(), self.registry.clone(), self.token.clone(), @@ -66,15 +66,11 @@ impl Login { /// execute [List] pub fn execute(&self) -> Result<(), anyhow::Error> { - let wasmer_dir = self.wasmer_dir(); - let token = self.get_token_or_ask_user(&wasmer_dir)?; - - let registry = wasmer_dir.registry_endpoint()?; - match wasmer_registry::login::login_and_save_token( - wasmer_dir.dir(), - registry.as_str(), - &token, - )? { + let env = self.wasmer_env(); + let token = self.get_token_or_ask_user(&env)?; + + let registry = env.registry_endpoint()?; + match wasmer_registry::login::login_and_save_token(env.dir(), registry.as_str(), &token)? { Some(s) => println!("Login for Wasmer user {:?} saved", s), None => println!( "Error: no user found on registry {:?} with token {:?}. Token saved regardless.", @@ -99,10 +95,12 @@ mod tests { wasmer_dir: temp.path().to_path_buf(), token: None, }; - let wasmer_dir = login.wasmer_dir(); + let env = login.wasmer_env(); + + let token = login.get_token_or_ask_user(&env).unwrap(); assert_eq!( - login.get_token_or_ask_user(&wasmer_dir).unwrap(), + token, "Please paste the login token from https://wasmer.wtf/settings/access-tokens" ); } @@ -115,8 +113,10 @@ mod tests { wasmer_dir: temp.path().to_path_buf(), token: Some("abc".to_string()), }; - let wasmer_dir = login.wasmer_dir(); + let env = login.wasmer_env(); + + let token = login.get_token_or_ask_user(&env).unwrap(); - assert_eq!(login.get_token_or_ask_user(&wasmer_dir).unwrap(), "abc"); + assert_eq!(token, "abc"); } } diff --git a/lib/cli/src/commands/publish.rs b/lib/cli/src/commands/publish.rs index 5ceb1eec26f..6dacea868bc 100644 --- a/lib/cli/src/commands/publish.rs +++ b/lib/cli/src/commands/publish.rs @@ -3,13 +3,13 @@ use std::path::Path; use clap::Parser; use wasmer_wasix::runtime::resolver::WapmSource; -use crate::WasmerDir; +use crate::WasmerEnv; /// Publish a package to the package registry. #[derive(Debug, Parser)] pub struct Publish { #[clap(flatten)] - wasmer_dir: WasmerDir, + env: WasmerEnv, /// Run the publish logic without sending anything to the registry server #[clap(long, name = "dry-run")] pub dry_run: bool, @@ -36,22 +36,18 @@ impl Publish { /// Executes `wasmer publish` pub fn execute(&self) -> Result<(), anyhow::Error> { let publish = wasmer_registry::package::builder::Publish { - registry: self - .wasmer_dir - .registry_endpoint() - .map(|u| u.to_string()) - .ok(), + registry: self.env.registry_endpoint().map(|u| u.to_string()).ok(), dry_run: self.dry_run, quiet: self.quiet, package_name: self.package_name.clone(), version: self.version.clone(), - token: self.wasmer_dir.token(), + token: self.env.token(), no_validate: self.no_validate, package_path: self.package_path.clone(), }; publish.execute().map_err(on_error)?; - if let Err(e) = invalidate_graphql_query_cache(self.wasmer_dir.dir()) { + if let Err(e) = invalidate_graphql_query_cache(self.env.dir()) { tracing::warn!( error = &*e, "Unable to invalidate the cache used for package version queries", diff --git a/lib/cli/src/commands/run.rs b/lib/cli/src/commands/run.rs index 502ce4bdfbc..60aebf9f975 100644 --- a/lib/cli/src/commands/run.rs +++ b/lib/cli/src/commands/run.rs @@ -50,7 +50,7 @@ use wasmer_wasix::{ use webc::{metadata::Manifest, Container}; use crate::{ - commands::run::wasi::Wasi, error::PrettyError, logging::Output, store::StoreOptions, WasmerDir, + commands::run::wasi::Wasi, error::PrettyError, logging::Output, store::StoreOptions, WasmerEnv, }; const TICK: Duration = Duration::from_millis(250); @@ -59,7 +59,7 @@ const TICK: Duration = Duration::from_millis(250); #[derive(Debug, Parser)] pub struct Run { #[clap(flatten)] - wasmer_dir: WasmerDir, + env: WasmerEnv, #[clap(flatten)] store: StoreOptions, #[clap(flatten)] @@ -106,9 +106,9 @@ impl Run { } let (store, _) = self.store.get_store()?; - let runtime = - self.wasi - .prepare_runtime(store.engine().clone(), &self.wasmer_dir, handle)?; + let runtime = self + .wasi + .prepare_runtime(store.engine().clone(), &self.env, handle)?; // This is a slow operation, so let's temporarily wrap the runtime with // something that displays progress @@ -352,7 +352,7 @@ impl Run { }; let store = StoreOptions::default(); Ok(Run { - wasmer_dir: WasmerDir::default(), + env: WasmerEnv::default(), store, wasi: Wasi::for_binfmt_interpreter()?, wcgi: WcgiOptions::default(), diff --git a/lib/cli/src/commands/run/wasi.rs b/lib/cli/src/commands/run/wasi.rs index d5a03da1a1a..1e2ff2424ef 100644 --- a/lib/cli/src/commands/run/wasi.rs +++ b/lib/cli/src/commands/run/wasi.rs @@ -37,7 +37,7 @@ use wasmer_wasix::{ use crate::{ utils::{parse_envvar, parse_mapdir}, - WasmerDir, + WasmerEnv, }; const WAPM_SOURCE_CACHE_TIMEOUT: Duration = Duration::from_secs(10 * 60); @@ -248,7 +248,7 @@ impl Wasi { pub fn prepare_runtime( &self, engine: Engine, - wasmer_dir: &WasmerDir, + env: &WasmerEnv, handle: Handle, ) -> Result { let mut rt = PluggableRuntime::new(Arc::new(TokioTaskManager::new(handle))); @@ -270,12 +270,12 @@ impl Wasi { let client = Arc::new(client); let package_loader = self - .prepare_package_loader(wasmer_dir.dir(), client.clone()) + .prepare_package_loader(env.dir(), client.clone()) .context("Unable to prepare the package loader")?; - let registry = self.prepare_source(wasmer_dir, client)?; + let registry = self.prepare_source(env, client)?; - let cache_dir = FileSystemCache::default_cache_dir(wasmer_dir.dir()); + let cache_dir = FileSystemCache::default_cache_dir(env.dir()); let module_cache = wasmer_wasix::runtime::module_cache::in_memory() .with_fallback(FileSystemCache::new(cache_dir)); @@ -327,7 +327,7 @@ impl Wasi { fn prepare_source( &self, - wasmer_dir: &WasmerDir, + env: &WasmerEnv, client: Arc, ) -> Result { let mut source = MultiSource::new(); @@ -342,13 +342,13 @@ impl Wasi { } source.add_source(preloaded); - let graphql_endpoint = self.graphql_endpoint(wasmer_dir)?; - let cache_dir = WapmSource::default_cache_dir(wasmer_dir.dir()); + let graphql_endpoint = self.graphql_endpoint(env)?; + let cache_dir = WapmSource::default_cache_dir(env.dir()); let wapm_source = WapmSource::new(graphql_endpoint, Arc::clone(&client)) .with_local_cache(cache_dir, WAPM_SOURCE_CACHE_TIMEOUT); source.add_source(wapm_source); - let cache_dir = WebSource::default_cache_dir(wasmer_dir.dir()); + let cache_dir = WebSource::default_cache_dir(env.dir()); source.add_source(WebSource::new(cache_dir, client)); source.add_source(FileSystemSource::default()); @@ -356,12 +356,12 @@ impl Wasi { Ok(source) } - fn graphql_endpoint(&self, wasmer_dir: &WasmerDir) -> Result { - if let Ok(endpoint) = wasmer_dir.registry_endpoint() { + fn graphql_endpoint(&self, env: &WasmerEnv) -> Result { + if let Ok(endpoint) = env.registry_endpoint() { return Ok(endpoint); } - let config = wasmer_dir.config()?; + let config = env.config()?; let graphql_endpoint = config.registry.get_graphql_url(); let graphql_endpoint = graphql_endpoint .parse() diff --git a/lib/cli/src/commands/whoami.rs b/lib/cli/src/commands/whoami.rs index adab954d0fb..72aa8c0e549 100644 --- a/lib/cli/src/commands/whoami.rs +++ b/lib/cli/src/commands/whoami.rs @@ -1,20 +1,20 @@ use clap::Parser; -use crate::WasmerDir; +use crate::WasmerEnv; #[derive(Debug, Parser)] /// The options for the `wasmer whoami` subcommand pub struct Whoami { #[clap(flatten)] - wasmer_dir: WasmerDir, + env: WasmerEnv, } impl Whoami { /// Execute `wasmer whoami` pub fn execute(&self) -> Result<(), anyhow::Error> { - let registry = self.wasmer_dir.registry_endpoint()?; + let registry = self.env.registry_endpoint()?; let (registry, username) = - wasmer_registry::whoami(self.wasmer_dir.dir(), Some(registry.as_str()), None)?; + wasmer_registry::whoami(self.env.dir(), Some(registry.as_str()), None)?; println!("logged into registry {registry:?} as user {username:?}"); Ok(()) } diff --git a/lib/cli/src/lib.rs b/lib/cli/src/lib.rs index 5e0a5cae53c..0adb77afdc0 100644 --- a/lib/cli/src/lib.rs +++ b/lib/cli/src/lib.rs @@ -27,9 +27,9 @@ pub mod package_source; pub mod store; pub mod suggestions; pub mod utils; -mod wasmer_dir; +mod wasmer_env; /// Version number of this crate. pub const VERSION: &str = env!("CARGO_PKG_VERSION"); -pub use crate::wasmer_dir::{Registry, WasmerDir, WASMER_DIR}; +pub use crate::wasmer_env::{Registry, WasmerEnv, WASMER_DIR}; diff --git a/lib/cli/src/wasmer_dir.rs b/lib/cli/src/wasmer_env.rs similarity index 91% rename from lib/cli/src/wasmer_dir.rs rename to lib/cli/src/wasmer_env.rs index cdd3b9fbf9d..3a34fa78b59 100644 --- a/lib/cli/src/wasmer_dir.rs +++ b/lib/cli/src/wasmer_env.rs @@ -5,10 +5,12 @@ use once_cell::sync::Lazy; use url::Url; use wasmer_registry::WasmerConfig; -/// Command-line flags for determining `$WASMER_DIR` and interactions with the -/// registry. +/// Command-line flags for determining the local "Wasmer Environment". +/// +/// This is where you access `$WASMER_DIR`, the `$WASMER_DIR/wasmer.toml` config +/// file, and specify the current registry. #[derive(Debug, Clone, PartialEq, clap::Parser)] -pub struct WasmerDir { +pub struct WasmerEnv { /// Set Wasmer's home directory #[clap(long, env = "WASMER_DIR", default_value = WASMER_DIR.as_os_str())] wasmer_dir: PathBuf, @@ -22,13 +24,13 @@ pub struct WasmerDir { token: Option, } -impl WasmerDir { +impl WasmerEnv { pub(crate) fn new( wasmer_dir: PathBuf, registry: Option, token: Option, ) -> Self { - WasmerDir { + WasmerEnv { wasmer_dir, registry, token, @@ -72,7 +74,7 @@ impl WasmerDir { } } -impl Default for WasmerDir { +impl Default for WasmerEnv { fn default() -> Self { Self { wasmer_dir: WASMER_DIR.clone(), diff --git a/tests/integration/cli/tests/config.rs b/tests/integration/cli/tests/config.rs index 9bbfcb122ce..994382fef23 100644 --- a/tests/integration/cli/tests/config.rs +++ b/tests/integration/cli/tests/config.rs @@ -1,5 +1,5 @@ +use assert_cmd::Command; use std::path::{Path, PathBuf}; -use std::process::Command; use wasmer_integration_tests_cli::{get_repo_root_path, get_wasmer_path}; fn get_wasmer_dir() -> Result { @@ -26,61 +26,50 @@ fn get_wasmer_dir() -> Result { } #[test] -fn wasmer_config_multiget() -> anyhow::Result<()> { - let bin_path = get_wasmer_dir()?.join("bin"); - let include_path = get_wasmer_dir()?.join("include"); - +fn wasmer_config_multiget() { + let wasmer_dir = get_wasmer_dir().unwrap(); + let bin_path = wasmer_dir.join("bin"); + let include_path = wasmer_dir.join("include"); let bin = format!("{}", bin_path.display()); let include = format!("-I{}", include_path.display()); - let output = Command::new(get_wasmer_path()) + let assert = Command::new(get_wasmer_path()) .arg("config") .arg("--bindir") .arg("--cflags") - .output()?; - - let lines = String::from_utf8_lossy(&output.stdout) - .lines() - .map(|s| s.trim().to_string()) - .collect::>(); + .assert(); - let expected = vec![bin, include]; - - assert_eq!(lines, expected); - - Ok(()) + assert + .success() + .stdout(predicates::str::contains(&bin)) + .stdout(predicates::str::contains(&include)); } #[test] -fn wasmer_config_error() -> anyhow::Result<()> { - let output = Command::new(get_wasmer_path()) +fn wasmer_config_error() { + let assert = Command::new(get_wasmer_path()) .arg("config") .arg("--bindir") .arg("--cflags") .arg("--pkg-config") - .output()?; + .assert(); - let lines = String::from_utf8_lossy(&output.stderr) - .lines() - .map(|s| s.trim().to_string()) - .collect::>(); - #[cfg(not(windows))] - let expected_1 = "Usage: wasmer config --bindir --cflags"; - #[cfg(windows)] - let expected_1 = "Usage: wasmer.exe config --bindir --cflags"; - - let expected = vec![ - "error: the argument '--bindir' cannot be used with '--pkg-config'", - "", - expected_1, - "", - "For more information, try '--help'.", - ]; - - assert_eq!(lines, expected); - - Ok(()) + let expected_1 = if cfg!(windows) { + "Usage: wasmer.exe config --bindir --cflags" + } else { + "Usage: wasmer config --bindir --cflags" + }; + + assert + .stderr(predicates::str::contains( + "error: the argument '--bindir' cannot be used with '--pkg-config'", + )) + .stderr(predicates::str::contains(expected_1)) + .stderr(predicates::str::contains( + "For more information, try '--help'.", + )); } + #[test] fn config_works() -> anyhow::Result<()> { let bindir = Command::new(get_wasmer_path()) From 2a34a9ed28b6899fd01e6b6d6082629876a000f5 Mon Sep 17 00:00:00 2001 From: Michael-F-Bryan Date: Wed, 21 Jun 2023 16:25:33 +0800 Subject: [PATCH 3/3] Moved WasmerEnv into the wasmer-registry crate --- Cargo.lock | 17 +++++---- lib/cli/Cargo.toml | 2 +- lib/cli/src/commands/add.rs | 4 +- lib/cli/src/commands/config.rs | 4 +- lib/cli/src/commands/init.rs | 11 +++--- lib/cli/src/commands/login.rs | 4 +- lib/cli/src/commands/publish.rs | 3 +- lib/cli/src/commands/run.rs | 6 +-- lib/cli/src/commands/run/wasi.rs | 6 +-- lib/cli/src/commands/whoami.rs | 3 +- lib/cli/src/lib.rs | 3 -- lib/registry/Cargo.toml | 49 +++++++++++++------------ lib/registry/src/lib.rs | 3 +- lib/{cli => registry}/src/wasmer_env.rs | 37 +++++++++---------- 14 files changed, 71 insertions(+), 81 deletions(-) rename lib/{cli => registry}/src/wasmer_env.rs (75%) diff --git a/Cargo.lock b/Cargo.lock index d334035ea1e..c99406c8aaa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -560,9 +560,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.4" +version = "4.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80672091db20273a15cf9fdd4e47ed43b5091ec9841bf4c6145c9dfbbcae09ed" +checksum = "2686c4115cb0810d9a984776e197823d08ec94f176549a89a9efded477c456dc" dependencies = [ "clap_builder", "clap_derive", @@ -575,15 +575,15 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1eef05769009513df2eb1c3b4613e7fad873a14c600ff025b08f250f59fee7de" dependencies = [ - "clap 4.3.4", + "clap 4.3.5", "log", ] [[package]] name = "clap_builder" -version = "4.3.4" +version = "4.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1458a1df40e1e2afebb7ab60ce55c1fa8f431146205aa5f4887e0b111c27636" +checksum = "2e53afce1efce6ed1f633cf0e57612fe51db54a1ee4fd8f8503d078fe02d69ae" dependencies = [ "anstream", "anstyle", @@ -5643,7 +5643,7 @@ dependencies = [ "cargo_metadata", "cfg-if 1.0.0", "chrono", - "clap 4.3.4", + "clap 4.3.5", "colored 2.0.0", "dialoguer", "dirs", @@ -5735,7 +5735,7 @@ dependencies = [ "atty", "bytesize", "cfg-if 1.0.0", - "clap 4.3.4", + "clap 4.3.5", "colored 2.0.0", "distance", "fern", @@ -5815,7 +5815,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "401220ca92419731ffb670b6d6f8442fc32b110f6e9bb5658c4cfa658c48ab32" dependencies = [ "anyhow", - "clap 4.3.4", + "clap 4.3.5", "clap-verbosity-flag", "comfy-table", "dialoguer", @@ -6025,6 +6025,7 @@ name = "wasmer-registry" version = "5.1.0" dependencies = [ "anyhow", + "clap 4.3.5", "console", "dirs", "filetime", diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml index b0a04270fa7..7000c9bd9ff 100644 --- a/lib/cli/Cargo.toml +++ b/lib/cli/Cargo.toml @@ -39,7 +39,7 @@ wasmer-wasix-experimental-io-devices = { version = "0.8.0", path = "../wasi-expe wasmer-wast = { version = "=4.0.0-beta.3", path = "../../tests/lib/wast", optional = true } wasmer-cache = { version = "=4.0.0-beta.3", path = "../cache", features = ["blake3-pure"] } wasmer-types = { version = "=4.0.0-beta.3", path = "../types", features = ["enable-serde"] } -wasmer-registry = { version = "5.1.0", path = "../registry", features = ["build-package"] } +wasmer-registry = { version = "5.1.0", path = "../registry", features = ["build-package", "clap"] } wasmer-object = { version = "=4.0.0-beta.3", path = "../object", optional = true } virtual-fs = { version = "0.6.0", path = "../virtual-fs", default-features = false, features = ["host-fs"] } virtual-net = { version = "0.3.0", path = "../virtual-net" } diff --git a/lib/cli/src/commands/add.rs b/lib/cli/src/commands/add.rs index f21a4a1423f..ddf33ba476d 100644 --- a/lib/cli/src/commands/add.rs +++ b/lib/cli/src/commands/add.rs @@ -2,9 +2,7 @@ use std::process::{Command, Stdio}; use anyhow::{Context, Error}; use clap::Parser; -use wasmer_registry::{Bindings, ProgrammingLanguage}; - -use crate::WasmerEnv; +use wasmer_registry::{wasmer_env::WasmerEnv, Bindings, ProgrammingLanguage}; /// Add a Wasmer package's bindings to your application. #[derive(Debug, Parser)] diff --git a/lib/cli/src/commands/config.rs b/lib/cli/src/commands/config.rs index 85934f1dcdc..119d8b67c07 100644 --- a/lib/cli/src/commands/config.rs +++ b/lib/cli/src/commands/config.rs @@ -1,8 +1,8 @@ -use crate::{WasmerEnv, VERSION}; +use crate::VERSION; use anyhow::{Context, Result}; use clap::Parser; use std::str::ParseBoolError; -use wasmer_registry::WasmerConfig; +use wasmer_registry::{wasmer_env::WasmerEnv, WasmerConfig}; #[derive(Debug, Parser)] /// The options for the `wasmer config` subcommand: `wasmer config get --OPTION` or `wasmer config set [FLAG]` diff --git a/lib/cli/src/commands/init.rs b/lib/cli/src/commands/init.rs index a69f53e93f4..393554833b4 100644 --- a/lib/cli/src/commands/init.rs +++ b/lib/cli/src/commands/init.rs @@ -1,12 +1,13 @@ +use std::{ + collections::HashMap, + path::{Path, PathBuf}, +}; + use anyhow::Context; use cargo_metadata::{CargoOpt, MetadataCommand}; use clap::Parser; use indexmap::IndexMap; -use std::collections::HashMap; -use std::path::Path; -use std::path::PathBuf; - -use crate::WasmerEnv; +use wasmer_registry::wasmer_env::WasmerEnv; static NOTE: &str = "# See more keys and definitions at https://docs.wasmer.io/registry/manifest"; diff --git a/lib/cli/src/commands/login.rs b/lib/cli/src/commands/login.rs index 9ffe9aca3f9..773fd97a7d1 100644 --- a/lib/cli/src/commands/login.rs +++ b/lib/cli/src/commands/login.rs @@ -4,13 +4,13 @@ use clap::Parser; #[cfg(not(test))] use dialoguer::Input; -use crate::{Registry, WasmerEnv}; +use wasmer_registry::wasmer_env::{Registry, WasmerEnv, WASMER_DIR}; /// Subcommand for listing packages #[derive(Debug, Clone, Parser)] pub struct Login { /// Set Wasmer's home directory - #[clap(long, env = "WASMER_DIR", default_value = crate::WASMER_DIR.as_os_str())] + #[clap(long, env = "WASMER_DIR", default_value = WASMER_DIR.as_os_str())] pub wasmer_dir: PathBuf, /// The registry to fetch packages from (inferred from the environment by /// default) diff --git a/lib/cli/src/commands/publish.rs b/lib/cli/src/commands/publish.rs index 6dacea868bc..0de1868b689 100644 --- a/lib/cli/src/commands/publish.rs +++ b/lib/cli/src/commands/publish.rs @@ -1,10 +1,9 @@ use std::path::Path; use clap::Parser; +use wasmer_registry::wasmer_env::WasmerEnv; use wasmer_wasix::runtime::resolver::WapmSource; -use crate::WasmerEnv; - /// Publish a package to the package registry. #[derive(Debug, Parser)] pub struct Publish { diff --git a/lib/cli/src/commands/run.rs b/lib/cli/src/commands/run.rs index 60aebf9f975..b5184b262bb 100644 --- a/lib/cli/src/commands/run.rs +++ b/lib/cli/src/commands/run.rs @@ -29,7 +29,7 @@ use wasmer::{ }; #[cfg(feature = "compiler")] use wasmer_compiler::ArtifactBuild; -use wasmer_registry::Package; +use wasmer_registry::{wasmer_env::WasmerEnv, Package}; use wasmer_wasix::{ bin_factory::BinaryPackage, runners::{MappedDirectory, Runner}, @@ -49,9 +49,7 @@ use wasmer_wasix::{ }; use webc::{metadata::Manifest, Container}; -use crate::{ - commands::run::wasi::Wasi, error::PrettyError, logging::Output, store::StoreOptions, WasmerEnv, -}; +use crate::{commands::run::wasi::Wasi, error::PrettyError, logging::Output, store::StoreOptions}; const TICK: Duration = Duration::from_millis(250); diff --git a/lib/cli/src/commands/run/wasi.rs b/lib/cli/src/commands/run/wasi.rs index 1e2ff2424ef..7bcb81e9de7 100644 --- a/lib/cli/src/commands/run/wasi.rs +++ b/lib/cli/src/commands/run/wasi.rs @@ -12,6 +12,7 @@ use tokio::runtime::Handle; use url::Url; use virtual_fs::{DeviceFile, FileSystem, PassthruFileSystem, RootFileSystemBuilder}; use wasmer::{Engine, Function, Instance, Memory32, Memory64, Module, RuntimeError, Store, Value}; +use wasmer_registry::wasmer_env::WasmerEnv; use wasmer_wasix::{ bin_factory::BinaryPackage, capabilities::Capabilities, @@ -35,10 +36,7 @@ use wasmer_wasix::{ WasiVersion, }; -use crate::{ - utils::{parse_envvar, parse_mapdir}, - WasmerEnv, -}; +use crate::utils::{parse_envvar, parse_mapdir}; const WAPM_SOURCE_CACHE_TIMEOUT: Duration = Duration::from_secs(10 * 60); diff --git a/lib/cli/src/commands/whoami.rs b/lib/cli/src/commands/whoami.rs index 72aa8c0e549..e6ec1dc2a1c 100644 --- a/lib/cli/src/commands/whoami.rs +++ b/lib/cli/src/commands/whoami.rs @@ -1,6 +1,5 @@ use clap::Parser; - -use crate::WasmerEnv; +use wasmer_registry::wasmer_env::WasmerEnv; #[derive(Debug, Parser)] /// The options for the `wasmer whoami` subcommand diff --git a/lib/cli/src/lib.rs b/lib/cli/src/lib.rs index 0adb77afdc0..5e9d4597aad 100644 --- a/lib/cli/src/lib.rs +++ b/lib/cli/src/lib.rs @@ -27,9 +27,6 @@ pub mod package_source; pub mod store; pub mod suggestions; pub mod utils; -mod wasmer_env; /// Version number of this crate. pub const VERSION: &str = env!("CARGO_PKG_VERSION"); - -pub use crate::wasmer_env::{Registry, WasmerEnv, WASMER_DIR}; diff --git a/lib/registry/Cargo.toml b/lib/registry/Cargo.toml index 33deb99227f..6964f2d5214 100644 --- a/lib/registry/Cargo.toml +++ b/lib/registry/Cargo.toml @@ -13,39 +13,40 @@ rust-version.workspace = true build-package = ["rusqlite", "indexmap", "wasmer-wasm-interface", "wasmparser", "rpassword", "minisign", "time"] [dependencies] -dirs = "4.0.0" -graphql_client = "0.11.0" -serde = { version = "1.0.145", features = ["derive"] } anyhow = "1.0.65" -futures-util = "0.3.25" -whoami = "1.2.3" -serde_json = "1.0.85" -url = "2.3.1" -thiserror = "1.0.37" -toml = "0.5.9" -wasmer-toml = "0.6.0" -tar = "0.4.38" +clap = { version = "4.3.5", default-features = false, features = ["derive", "env"], optional = true } +console = "0.15.2" +dirs = "4.0.0" +filetime = "0.2.19" flate2 = "1.0.24" -semver = "1.0.14" -lzma-rs = "0.2.0" +futures-util = "0.3.25" +graphql_client = "0.11.0" hex = "0.4.3" -tokio = "1.24.0" -log = "0.4.17" -regex = "1.7.0" -filetime = "0.2.19" -tldextract = "0.6.0" -console = "0.15.2" +indexmap = { version = "1.9.3", optional = true } indicatif = "0.17.2" lazy_static = "1.4.0" -tempfile = "3.4.0" +log = "0.4.17" +lzma-rs = "0.2.0" +minisign = { version = "0.7.2", optional = true } +regex = "1.7.0" +reqwest = { version = "0.11.12", default-features = false, features = ["blocking", "multipart", "json", "stream"] } +rpassword = { version = "7.2.0", optional = true } rusqlite = { version = "0.28.0", optional = true, features = ["bundled"] } +semver = "1.0.14" +serde = { version = "1.0.145", features = ["derive"] } +serde_json = "1.0.85" +tar = "0.4.38" +tempfile = "3.4.0" +thiserror = "1.0.37" time = { version = "0.3.17", default-features = false, features = ["parsing", "std", "formatting"], optional = true } -indexmap = { version = "1.9.3", optional = true } +tldextract = "0.6.0" +tokio = "1.24.0" +toml = "0.5.9" +url = "2.3.1" +wasmer-toml = "0.6.0" wasmer-wasm-interface = { version = "4.0.0-beta.3", path = "../wasm-interface", optional = true } wasmparser = { version = "0.51.4", optional = true } -rpassword = { version = "7.2.0", optional = true } -minisign = { version = "0.7.2", optional = true } -reqwest = { version = "0.11.12", default-features = false, features = ["blocking", "multipart", "json", "stream"] } +whoami = "1.2.3" [dev-dependencies] pretty_assertions = "1.3.0" diff --git a/lib/registry/src/lib.rs b/lib/registry/src/lib.rs index 522f174871a..88ce6b5948f 100644 --- a/lib/registry/src/lib.rs +++ b/lib/registry/src/lib.rs @@ -18,8 +18,9 @@ pub mod package; pub mod publish; pub mod types; pub mod utils; +pub mod wasmer_env; -pub use client::RegistryClient; +pub use crate::client::RegistryClient; use std::{ fmt, diff --git a/lib/cli/src/wasmer_env.rs b/lib/registry/src/wasmer_env.rs similarity index 75% rename from lib/cli/src/wasmer_env.rs rename to lib/registry/src/wasmer_env.rs index 3a34fa78b59..b7a2c214dc1 100644 --- a/lib/cli/src/wasmer_env.rs +++ b/lib/registry/src/wasmer_env.rs @@ -1,35 +1,31 @@ use std::path::{Path, PathBuf}; +use crate::WasmerConfig; use anyhow::{Context, Error}; -use once_cell::sync::Lazy; use url::Url; -use wasmer_registry::WasmerConfig; /// Command-line flags for determining the local "Wasmer Environment". /// /// This is where you access `$WASMER_DIR`, the `$WASMER_DIR/wasmer.toml` config /// file, and specify the current registry. -#[derive(Debug, Clone, PartialEq, clap::Parser)] +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "clap", derive(clap::Parser))] pub struct WasmerEnv { /// Set Wasmer's home directory - #[clap(long, env = "WASMER_DIR", default_value = WASMER_DIR.as_os_str())] + #[cfg_attr(feature = "clap", clap(long, env = "WASMER_DIR", default_value = WASMER_DIR.as_os_str()))] wasmer_dir: PathBuf, /// The registry to fetch packages from (inferred from the environment by /// default) - #[clap(long, env = "WASMER_REGISTRY")] + #[cfg_attr(feature = "clap", clap(long, env = "WASMER_REGISTRY"))] registry: Option, /// The API token to use when communicating with the registry (inferred from /// the environment by default) - #[clap(long, env = "WASMER_TOKEN")] + #[cfg_attr(feature = "clap", clap(long, env = "WASMER_TOKEN"))] token: Option, } impl WasmerEnv { - pub(crate) fn new( - wasmer_dir: PathBuf, - registry: Option, - token: Option, - ) -> Self { + pub fn new(wasmer_dir: PathBuf, registry: Option, token: Option) -> Self { WasmerEnv { wasmer_dir, registry, @@ -84,18 +80,19 @@ impl Default for WasmerEnv { } } -/// The default value for `$WASMER_DIR`. -pub static WASMER_DIR: Lazy = - Lazy::new(|| match wasmer_registry::WasmerConfig::get_wasmer_dir() { +lazy_static::lazy_static! { + /// The default value for `$WASMER_DIR`. + pub static ref WASMER_DIR: PathBuf = match crate::WasmerConfig::get_wasmer_dir() { Ok(path) => path, Err(e) => { - if let Some(install_prefix) = std::env::var_os("WASMER_INSTALL_PREFIX") { - PathBuf::from(install_prefix) - } else { - panic!("Unable to determine the wasmer dir: {e}"); + if let Some(install_prefix) = option_env!("WASMER_INSTALL_PREFIX") { + return PathBuf::from(install_prefix); } + + panic!("Unable to determine the wasmer dir: {e}"); } - }); + }; +} /// A registry as specified by the user. #[derive(Debug, Clone, PartialEq, Eq)] @@ -109,7 +106,7 @@ impl Registry { /// Get the GraphQL endpoint for this [`Registry`]. pub fn graphql_endpoint(&self) -> Result { - let url = wasmer_registry::format_graphql(self.as_str()).parse()?; + let url = crate::format_graphql(self.as_str()).parse()?; Ok(url) } }