diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index ab2ea9a7..b08f8dde 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -5,6 +5,22 @@ pub mod v1; use serde::{de::Unexpected, Deserialize, Serialize}; +/// Relative URL path for the `WellKnownConfig`. +pub const WELL_KNOWN_PATH: &str = ".well-known/wasm-pkg/registry.json"; + +/// This config allows a domain to point to another URL where the registry +/// API is hosted. +#[derive(Debug, Default, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct WellKnownConfig { + /// For OCI registries, the domain name where the registry is hosted. + pub oci_registry: Option, + /// For OCI registries, a name prefix to use before the namespace. + pub oci_namespace_prefix: Option, + /// For Warg registries, the URL where the registry is hosted. + pub warg_url: Option, +} + /// A utility type for serializing and deserializing constant status codes. struct Status; diff --git a/crates/client/src/api.rs b/crates/client/src/api.rs index 3e645aa0..8b600a96 100644 --- a/crates/client/src/api.rs +++ b/crates/client/src/api.rs @@ -12,20 +12,24 @@ use secrecy::{ExposeSecret, Secret}; use serde::de::DeserializeOwned; use std::borrow::Cow; use thiserror::Error; -use warg_api::v1::{ - content::{ContentError, ContentSourcesResponse}, - fetch::{ - FetchError, FetchLogsRequest, FetchLogsResponse, FetchPackageNamesRequest, - FetchPackageNamesResponse, +use warg_api::{ + v1::{ + content::{ContentError, ContentSourcesResponse}, + fetch::{ + FetchError, FetchLogsRequest, FetchLogsResponse, FetchPackageNamesRequest, + FetchPackageNamesResponse, + }, + ledger::{LedgerError, LedgerSourcesResponse}, + monitor::{CheckpointVerificationResponse, MonitorError}, + package::{ContentSource, PackageError, PackageRecord, PublishRecordRequest}, + paths, + proof::{ + ConsistencyRequest, ConsistencyResponse, InclusionRequest, InclusionResponse, + ProofError, + }, + REGISTRY_HEADER_NAME, REGISTRY_HINT_HEADER_NAME, }, - ledger::{LedgerError, LedgerSourcesResponse}, - monitor::{CheckpointVerificationResponse, MonitorError}, - package::{ContentSource, PackageError, PackageRecord, PublishRecordRequest}, - paths, - proof::{ - ConsistencyRequest, ConsistencyResponse, InclusionRequest, InclusionResponse, ProofError, - }, - REGISTRY_HEADER_NAME, REGISTRY_HINT_HEADER_NAME, + WellKnownConfig, WELL_KNOWN_PATH, }; use warg_crypto::hash::{AnyHash, HashError, Sha256}; use warg_protocol::{ @@ -107,6 +111,9 @@ pub enum ClientError { /// The provided log was not found with hint header. #[error("log `{0}` was not found in this registry, but the registry provided the hint header: `{1:?}`")] LogNotFoundWithHint(LogId, HeaderValue), + /// Invalid well-known config. + #[error("registry `{0}` returned an invalid well-known config")] + InvalidWellKnownConfig(String), /// An other error occurred during the requested operation. #[error(transparent)] Other(#[from] anyhow::Error), @@ -216,6 +223,37 @@ impl Client { pub fn url(&self) -> &RegistryUrl { &self.url } + /// Gets the `.well-known` configuration registry URL. + pub async fn well_known_config(&self) -> Result, ClientError> { + let url = self.url.join(WELL_KNOWN_PATH); + tracing::debug!(url, "getting `.well-known` config",); + + let res = self.client.get(url).send().await?; + + if !res.status().is_success() { + tracing::debug!( + "the `.well-known` config request returned HTTP status `{status}`", + status = res.status() + ); + return Ok(None); + } + + if let Some(warg_url) = res + .json::() + .await + .map_err(|e| { + tracing::debug!("parsing `.well-known` config failed: {e}"); + ClientError::InvalidWellKnownConfig(self.url.registry_domain().to_string()) + })? + .warg_url + { + Ok(Some(RegistryUrl::new(warg_url)?)) + } else { + tracing::debug!("the `.well-known` config did not have a `wargUrl` set"); + Ok(None) + } + } + /// Gets the latest checkpoint from the registry. pub async fn latest_checkpoint( &self, diff --git a/crates/client/src/config.rs b/crates/client/src/config.rs index 02a58e15..729f01da 100644 --- a/crates/client/src/config.rs +++ b/crates/client/src/config.rs @@ -300,13 +300,8 @@ impl Config { pub(crate) fn storage_paths_for_url( &self, - url: Option<&str>, + registry_url: RegistryUrl, ) -> Result { - let registry_url = RegistryUrl::new( - url.or(self.home_url.as_deref()) - .ok_or(ClientError::NoHomeRegistryUrl)?, - )?; - let label = registry_url.safe_label(); let registries_dir = self.registries_dir()?.join(label); let content_dir = self.content_dir()?; diff --git a/crates/client/src/lib.rs b/crates/client/src/lib.rs index 5ea97b48..94b76297 100644 --- a/crates/client/src/lib.rs +++ b/crates/client/src/lib.rs @@ -57,6 +57,10 @@ pub use self::registry_url::RegistryUrl; const DEFAULT_WAIT_INTERVAL: Duration = Duration::from_secs(1); +/// For Bytecode Alliance projects, the default registry is set to `bytecodealliance.org`. +/// The `.well-known` config path may resolve to another domain where the registry is hosted. +pub const DEFAULT_REGISTRY: &str = "bytecodealliance.org"; + /// A client for a Warg registry. pub struct Client where @@ -1358,6 +1362,39 @@ pub enum StorageLockResult { } impl FileSystemClient { + async fn storage_paths( + url: Option<&str>, + config: &Config, + disable_interactive: bool, + ) -> Result { + let checking_url_for_well_known = RegistryUrl::new( + url.or(config.home_url.as_deref()) + .unwrap_or(DEFAULT_REGISTRY), + )?; + + let url = if let Some(warg_url) = + api::Client::new(checking_url_for_well_known.to_string(), None)? + .well_known_config() + .await? + { + if !disable_interactive && warg_url != checking_url_for_well_known { + println!( + "Resolved `{well_known}` to registry hosted on `{registry}`", + well_known = checking_url_for_well_known.registry_domain(), + registry = warg_url.registry_domain(), + ); + } + warg_url + } else { + RegistryUrl::new( + url.or(config.home_url.as_deref()) + .ok_or(ClientError::NoHomeRegistryUrl)?, + )? + }; + + config.storage_paths_for_url(url) + } + /// Attempts to create a client for the given registry URL. /// /// If the URL is `None`, the home registry URL is used; if there is no home registry @@ -1366,30 +1403,20 @@ impl FileSystemClient { /// If a lock cannot be acquired for a storage directory, then /// `NewClientResult::Blocked` is returned with the path to the /// directory that could not be locked. - pub fn try_new_with_config( - url: Option<&str>, + pub async fn try_new_with_config( + registry: Option<&str>, config: &Config, mut auth_token: Option>, ) -> Result, ClientError> { + let disable_interactive = + cfg!(not(feature = "cli-interactive")) || config.disable_interactive; + let StoragePaths { registry_url: url, registries_dir, content_dir, namespace_map_path, - } = config.storage_paths_for_url(url)?; - - let (packages, content, namespace_map) = match ( - FileSystemRegistryStorage::try_lock(registries_dir.clone())?, - FileSystemContentStorage::try_lock(content_dir.clone())?, - FileSystemNamespaceMapStorage::new(namespace_map_path.clone()), - ) { - (Some(packages), Some(content), namespace_map) => (packages, content, namespace_map), - (None, _, _) => return Ok(StorageLockResult::NotAcquired(registries_dir)), - (_, None, _) => return Ok(StorageLockResult::NotAcquired(content_dir)), - }; - - let disable_interactive = - cfg!(not(feature = "cli-interactive")) || config.disable_interactive; + } = Self::storage_paths(registry, config, disable_interactive).await?; let (keyring_backend, keys) = if cfg!(feature = "keyring") { (config.keyring_backend.clone(), config.keys.clone()) @@ -1402,6 +1429,16 @@ impl FileSystemClient { auth_token = crate::keyring::Keyring::from_config(config)?.get_auth_token(&url)? } + let (packages, content, namespace_map) = match ( + FileSystemRegistryStorage::try_lock(registries_dir.clone())?, + FileSystemContentStorage::try_lock(content_dir.clone())?, + FileSystemNamespaceMapStorage::new(namespace_map_path.clone()), + ) { + (Some(packages), Some(content), namespace_map) => (packages, content, namespace_map), + (None, _, _) => return Ok(StorageLockResult::NotAcquired(registries_dir)), + (_, None, _) => return Ok(StorageLockResult::NotAcquired(content_dir)), + }; + Ok(StorageLockResult::Acquired(Self::new( url.into_url(), packages, @@ -1427,10 +1464,11 @@ impl FileSystemClient { /// /// Same as calling `try_new_with_config` with /// `Config::from_default_file()?.unwrap_or_default()`. - pub fn try_new_with_default_config( + pub async fn try_new_with_default_config( url: Option<&str>, ) -> Result, ClientError> { Self::try_new_with_config(url, &Config::from_default_file()?.unwrap_or_default(), None) + .await } /// Creates a client for the given registry URL. @@ -1439,20 +1477,20 @@ impl FileSystemClient { /// URL, an error is returned. /// /// This method blocks if storage locks cannot be acquired. - pub fn new_with_config( - url: Option<&str>, + pub async fn new_with_config( + registry: Option<&str>, config: &Config, mut auth_token: Option>, ) -> Result { + let disable_interactive = + cfg!(not(feature = "cli-interactive")) || config.disable_interactive; + let StoragePaths { - registry_url, + registry_url: url, registries_dir, content_dir, namespace_map_path, - } = config.storage_paths_for_url(url)?; - - let disable_interactive = - cfg!(not(feature = "cli-interactive")) || config.disable_interactive; + } = Self::storage_paths(registry, config, disable_interactive).await?; let (keyring_backend, keys) = if cfg!(feature = "keyring") { (config.keyring_backend.clone(), config.keys.clone()) @@ -1462,12 +1500,11 @@ impl FileSystemClient { #[cfg(feature = "keyring")] if auth_token.is_none() && config.keyring_auth { - auth_token = - crate::keyring::Keyring::from_config(config)?.get_auth_token(®istry_url)? + auth_token = crate::keyring::Keyring::from_config(config)?.get_auth_token(&url)? } Self::new( - registry_url.into_url(), + url.into_url(), FileSystemRegistryStorage::lock(registries_dir)?, FileSystemContentStorage::lock(content_dir)?, FileSystemNamespaceMapStorage::new(namespace_map_path), @@ -1489,8 +1526,8 @@ impl FileSystemClient { /// /// Same as calling `new_with_config` with /// `Config::from_default_file()?.unwrap_or_default()`. - pub fn new_with_default_config(url: Option<&str>) -> Result { - Self::new_with_config(url, &Config::from_default_file()?.unwrap_or_default(), None) + pub async fn new_with_default_config(url: Option<&str>) -> Result { + Self::new_with_config(url, &Config::from_default_file()?.unwrap_or_default(), None).await } } diff --git a/crates/client/src/registry_url.rs b/crates/client/src/registry_url.rs index 44845b20..135ae971 100644 --- a/crates/client/src/registry_url.rs +++ b/crates/client/src/registry_url.rs @@ -5,7 +5,7 @@ use url::{Host, Url}; /// The base URL of a registry server. // Note: The inner Url always has a scheme and host. -#[derive(Clone)] +#[derive(Clone, Eq, PartialEq)] pub struct RegistryUrl(Url); impl RegistryUrl { diff --git a/src/commands.rs b/src/commands.rs index 07be59b0..96467a2a 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -66,9 +66,11 @@ impl CommonOptions { } /// Creates the warg client to use. - pub fn create_client(&self, config: &Config) -> Result { + pub async fn create_client(&self, config: &Config) -> Result { let client = - match FileSystemClient::try_new_with_config(self.registry.as_deref(), config, None)? { + match FileSystemClient::try_new_with_config(self.registry.as_deref(), config, None) + .await? + { StorageLockResult::Acquired(client) => Ok(client), StorageLockResult::NotAcquired(path) => { println!( @@ -76,7 +78,7 @@ impl CommonOptions { path = path.display() ); - FileSystemClient::new_with_config(self.registry.as_deref(), config, None) + FileSystemClient::new_with_config(self.registry.as_deref(), config, None).await } }?; Ok(client) diff --git a/src/commands/bundle.rs b/src/commands/bundle.rs index 9e144771..004b0209 100644 --- a/src/commands/bundle.rs +++ b/src/commands/bundle.rs @@ -19,7 +19,7 @@ impl BundleCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; let info = client.package(&self.package).await?; client.bundle_component(&info).await?; diff --git a/src/commands/clear.rs b/src/commands/clear.rs index b9ce20a7..01f7ba7d 100644 --- a/src/commands/clear.rs +++ b/src/commands/clear.rs @@ -14,7 +14,7 @@ impl ClearCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; println!("clearing local content cache..."); client.clear_content_cache().await?; diff --git a/src/commands/config.rs b/src/commands/config.rs index 03e759bf..f8f48765 100644 --- a/src/commands/config.rs +++ b/src/commands/config.rs @@ -139,7 +139,7 @@ impl ConfigCommand { // reset when changing home registry if changing_home_registry { - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; client.reset_namespaces().await?; client.reset_registry().await?; } diff --git a/src/commands/dependencies.rs b/src/commands/dependencies.rs index e8174a15..eee893db 100644 --- a/src/commands/dependencies.rs +++ b/src/commands/dependencies.rs @@ -31,7 +31,7 @@ impl DependenciesCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; let info = client.package(&self.package).await?; Self::print_package_info(&client, &info).await?; diff --git a/src/commands/download.rs b/src/commands/download.rs index 7b750ee3..33853cd9 100644 --- a/src/commands/download.rs +++ b/src/commands/download.rs @@ -28,7 +28,7 @@ impl DownloadCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; println!("Downloading `{name}`...", name = self.name); diff --git a/src/commands/info.rs b/src/commands/info.rs index 8c3ba826..83ac1066 100644 --- a/src/commands/info.rs +++ b/src/commands/info.rs @@ -29,9 +29,9 @@ impl InfoCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; - println!("\nRegistry: {url}", url = client.url()); + print!("\nRegistry: {url} ", url = client.url().registry_domain()); if config.keyring_auth && Keyring::from_config(&config)? .get_auth_token(client.url())? diff --git a/src/commands/lock.rs b/src/commands/lock.rs index 73f9e532..478ebd5a 100644 --- a/src/commands/lock.rs +++ b/src/commands/lock.rs @@ -19,7 +19,7 @@ impl LockCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; let info = client.package(&self.package).await?; client.lock_component(&info).await?; diff --git a/src/commands/login.rs b/src/commands/login.rs index 905ff1dd..80425f9c 100644 --- a/src/commands/login.rs +++ b/src/commands/login.rs @@ -16,6 +16,11 @@ pub struct LoginCommand { #[clap(flatten)] pub common: CommonOptions, + /// The URL of the registry to use. + #[clap(value_name = "URL")] + #[arg(hide = true)] + pub registry_url: Option, + /// Ignore federation hints. #[clap(long)] pub ignore_federation_hints: bool, @@ -31,7 +36,13 @@ pub struct LoginCommand { impl LoginCommand { /// Executes the command. - pub async fn exec(self) -> Result<()> { + pub async fn exec(mut self) -> Result<()> { + if self.registry_url.is_some() { + if self.common.registry.is_some() { + bail!("Registry URL provided in two different arguments. Use only one."); + } + self.common.registry = self.registry_url; + } let mut config = self.common.read_config()?; let mut registry_url = &self .common @@ -52,6 +63,8 @@ impl LoginCommand { bail!("Please set your registry: warg login --registry "); } + let mut changing_home_registry = false; + if registry_url.is_some() && registry_url != &config.home_url && Confirm::with_theme(&ColorfulTheme::default()) @@ -66,9 +79,7 @@ impl LoginCommand { config.write_to_file(&Config::default_config_path()?)?; // reset if changing home registry - let client = self.common.create_client(&config)?; - client.reset_namespaces().await?; - client.reset_registry().await?; + changing_home_registry = true; } else if registry_url.is_none() { registry_url = &config.home_url; } @@ -76,9 +87,26 @@ impl LoginCommand { let keyring = Keyring::from_config(&config)?; config.keyring_auth = true; + let client = if *registry_url == config.home_url { + self.common.create_client(&config).await? + } else { + let mut config = config.clone(); + config.home_url.clone_from(registry_url); + self.common.create_client(&config).await? + }; + + // the client may resolve the registry to well-known on a different registry host, + // so replace the `registry_url` with that host + let registry_url = Some(client.url().to_string()); + + if changing_home_registry { + client.reset_namespaces().await?; + client.reset_registry().await?; + } + let prompt = format!( "Enter auth token for registry: {registry}", - registry = registry_url.as_deref().unwrap() + registry = client.url().registry_domain(), ); if config.keys.is_empty() { diff --git a/src/commands/logout.rs b/src/commands/logout.rs index 505a37c6..685c02d6 100644 --- a/src/commands/logout.rs +++ b/src/commands/logout.rs @@ -1,4 +1,4 @@ -use anyhow::Result; +use anyhow::{bail, Result}; use clap::Args; use warg_client::{keyring::Keyring, Config, RegistryUrl}; @@ -10,11 +10,22 @@ pub struct LogoutCommand { /// The common command options. #[clap(flatten)] pub common: CommonOptions, + + /// The URL of the registry to use. + #[clap(value_name = "URL")] + #[arg(hide = true)] + pub registry_url: Option, } impl LogoutCommand { /// Executes the command. - pub async fn exec(self) -> Result<()> { + pub async fn exec(mut self) -> Result<()> { + if self.registry_url.is_some() { + if self.common.registry.is_some() { + bail!("Registry URL provided in two different arguments. Use only one."); + } + self.common.registry = self.registry_url; + } let mut config = self.common.read_config()?; let registry_url = &self .common @@ -39,7 +50,7 @@ impl LogoutCommand { } println!( "Logged out of registry: {registry}", - registry = registry_url_str + registry = registry_url.registry_domain(), ); Ok(()) } diff --git a/src/commands/publish.rs b/src/commands/publish.rs index 05af2ff0..3784841c 100644 --- a/src/commands/publish.rs +++ b/src/commands/publish.rs @@ -119,7 +119,7 @@ impl PublishInitCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; let registry_domain = client.get_warg_registry(self.name.namespace()).await?; let signing_key = self.common.signing_key(registry_domain.as_ref()).await?; @@ -190,7 +190,7 @@ impl PublishReleaseCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; let registry_domain = client.get_warg_registry(self.name.namespace()).await?; let signing_key = self.common.signing_key(registry_domain.as_ref()).await?; @@ -291,7 +291,7 @@ Yank `{version}` of `{package}`?", } let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; let registry_domain = client.get_warg_registry(self.name.namespace()).await?; let signing_key = self.common.signing_key(registry_domain.as_ref()).await?; @@ -369,7 +369,7 @@ impl PublishGrantCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; let registry_domain = client.get_warg_registry(self.name.namespace()).await?; let signing_key = self.common.signing_key(registry_domain.as_ref()).await?; @@ -451,7 +451,7 @@ impl PublishRevokeCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; let registry_domain = client.get_warg_registry(self.name.namespace()).await?; let signing_key = self.common.signing_key(registry_domain.as_ref()).await?; @@ -520,7 +520,7 @@ impl PublishStartCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; match client.registry().load_publish().await? { Some(info) => bail!("a publish is already in progress for package `{name}`; use `publish abort` to abort the current publish", name = info.name), @@ -554,7 +554,7 @@ impl PublishListCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; match client.registry().load_publish().await? { Some(info) => { @@ -610,7 +610,7 @@ impl PublishAbortCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; match client.registry().load_publish().await? { Some(info) => { @@ -642,7 +642,7 @@ impl PublishSubmitCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; match client.registry().load_publish().await? { Some(info) => { @@ -720,7 +720,7 @@ impl PublishWaitCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; let record_id = RecordId::from(self.record_id); println!( diff --git a/src/commands/reset.rs b/src/commands/reset.rs index b6e6bffb..d14cfc8f 100644 --- a/src/commands/reset.rs +++ b/src/commands/reset.rs @@ -14,7 +14,7 @@ impl ResetCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; println!("resetting local registry data..."); client.reset_registry().await?; diff --git a/src/commands/update.rs b/src/commands/update.rs index 9bc8c29e..aa7214c4 100644 --- a/src/commands/update.rs +++ b/src/commands/update.rs @@ -14,7 +14,7 @@ impl UpdateCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { let config = self.common.read_config()?; - let client = self.common.create_client(&config)?; + let client = self.common.create_client(&config).await?; println!("updating package logs to the latest available versions..."); client.update().await?; diff --git a/tests/client.rs b/tests/client.rs index 16f87b97..e97a58fe 100644 --- a/tests/client.rs +++ b/tests/client.rs @@ -9,8 +9,8 @@ use warg_protocol::registry::PackageName; pub mod support; -fn create_client(config: &Config) -> Result { - match FileSystemClient::try_new_with_config(None, config, None)? { +async fn create_client(config: &Config) -> Result { + match FileSystemClient::try_new_with_config(None, config, None).await? { StorageLockResult::Acquired(client) => Ok(client), _ => bail!("failed to acquire storage lock"), } @@ -23,7 +23,7 @@ async fn client_incrementally_fetches() -> Result<()> { let (_server, config) = spawn_server(&root().await?, None, None, None).await?; - let client = create_client(&config)?; + let client = create_client(&config).await?; let signing_key = support::test_signing_key(); // Store a single component that will be used for every release @@ -83,7 +83,7 @@ async fn client_incrementally_fetches() -> Result<()> { .context("failed to remove registries directory")?; // Recreate the client with the same config - let client = create_client(&config)?; + let client = create_client(&config).await?; // Regression test: update on empty registry storage client.update().await?; diff --git a/tests/depsolve.rs b/tests/depsolve.rs index b3e33f07..3b153932 100644 --- a/tests/depsolve.rs +++ b/tests/depsolve.rs @@ -17,7 +17,7 @@ pub mod support; async fn depsolve() -> Result<()> { let (_server, config) = spawn_server(&root().await?, None, None, None).await?; - let client = create_client(&config)?; + let client = create_client(&config).await?; let signing_key = support::test_signing_key(); let mut head = publish_package( diff --git a/tests/postgres/mod.rs b/tests/postgres/mod.rs index 645ddce4..ce5a45a1 100644 --- a/tests/postgres/mod.rs +++ b/tests/postgres/mod.rs @@ -95,7 +95,7 @@ async fn it_works_with_postgres() -> TestResult { fs::remove_dir_all(root.join("content"))?; fs::remove_dir_all(root.join("registries"))?; - let client = create_client(&config)?; + let client = create_client(&config).await?; client.fetch_packages(packages.iter()).await?; // Finally, after a restart, ensure the packages can be downloaded diff --git a/tests/server.rs b/tests/server.rs index e2b7a6ff..351816f3 100644 --- a/tests/server.rs +++ b/tests/server.rs @@ -71,7 +71,7 @@ async fn test_component_publishing(config: &Config) -> Result<()> { const PACKAGE_VERSION: &str = "0.1.0"; let name = PackageName::new(PACKAGE_NAME)?; - let client = create_client(config)?; + let client = create_client(config).await?; let signing_key = test_signing_key(); let digest = publish_component( &client, @@ -118,7 +118,7 @@ async fn test_package_yanking(config: &Config) -> Result<()> { // Publish release let name = PackageName::new(PACKAGE_NAME)?; - let client = create_client(config)?; + let client = create_client(config).await?; let signing_key = test_signing_key(); publish( &client, @@ -157,7 +157,7 @@ async fn test_wit_publishing(config: &Config) -> Result<()> { const PACKAGE_VERSION: &str = "0.1.0"; let name = PackageName::new(PACKAGE_NAME)?; - let client = create_client(config)?; + let client = create_client(config).await?; let signing_key = test_signing_key(); let digest = publish_wit( &client, @@ -205,7 +205,7 @@ async fn test_wasm_content_policy(config: &Config) -> Result<()> { // Publish empty content to the server // This should be rejected by policy because it is not valid WebAssembly let name = PackageName::new(PACKAGE_NAME)?; - let client = create_client(config)?; + let client = create_client(config).await?; let signing_key = test_signing_key(); match publish( &client, @@ -263,7 +263,7 @@ async fn test_unauthorized_signing_key(config: &Config) -> Result<()> { // Start by publishing a new component package let name = PackageName::new(PACKAGE_NAME)?; - let client = create_client(config)?; + let client = create_client(config).await?; let signing_key = test_signing_key(); publish_component( &client, @@ -299,7 +299,7 @@ async fn test_unknown_signing_key(config: &Config) -> Result<()> { // Start by publishing a new component package let name = PackageName::new(PACKAGE_NAME)?; - let client = create_client(config)?; + let client = create_client(config).await?; let signing_key = test_signing_key(); publish_component( &client, @@ -391,7 +391,7 @@ async fn test_custom_content_url(config: &Config) -> Result<()> { const PACKAGE_VERSION: &str = "0.1.0"; let name = PackageName::new(PACKAGE_NAME)?; - let client = create_client(config)?; + let client = create_client(config).await?; let signing_key = test_signing_key(); let digest = publish_component( &client, diff --git a/tests/support/mod.rs b/tests/support/mod.rs index a2954537..bab73be4 100644 --- a/tests/support/mod.rs +++ b/tests/support/mod.rs @@ -43,8 +43,8 @@ pub fn test_signing_key() -> PrivateKey { PrivateKey::decode(key.to_string()).unwrap() } -pub fn create_client(config: &warg_client::Config) -> Result { - match FileSystemClient::try_new_with_config(None, config, None)? { +pub async fn create_client(config: &warg_client::Config) -> Result { + match FileSystemClient::try_new_with_config(None, config, None).await? { StorageLockResult::Acquired(client) => Ok(client), _ => bail!("failed to acquire storage lock"), }