use crate::{
config::{UpdateRegistry, WasmerConfig, WasmerEnv},
VERSION,
};
use anyhow::{Context, Result};
use clap::Parser;
use std::str::ParseBoolError;
use super::AsyncCliCommand;
#[derive(Debug, Parser)]
pub struct Config {
#[clap(flatten)]
env: WasmerEnv,
#[clap(flatten)]
flags: Flags,
#[clap(subcommand)]
set: Option<GetOrSet>,
}
#[derive(Debug, Parser)]
pub struct Flags {
#[clap(long, conflicts_with = "pkg_config")]
prefix: bool,
#[clap(long, conflicts_with = "pkg_config")]
bindir: bool,
#[clap(long, conflicts_with = "pkg_config")]
includedir: bool,
#[clap(long, conflicts_with = "pkg_config")]
libdir: bool,
#[clap(long, conflicts_with = "pkg_config")]
libs: bool,
#[clap(long, conflicts_with = "pkg_config")]
cflags: bool,
#[clap(long, conflicts_with = "pkg_config")]
config_path: bool,
#[clap(long)]
pkg_config: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Parser)]
pub enum GetOrSet {
#[clap(subcommand)]
Get(RetrievableConfigField),
#[clap(subcommand)]
Set(StorableConfigField),
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Parser)]
pub enum RetrievableConfigField {
#[clap(name = "registry.url")]
RegistryUrl,
#[clap(name = "registry.token")]
RegistryToken,
#[clap(name = "telemetry.enabled")]
TelemetryEnabled,
#[clap(name = "update-notifications.enabled")]
UpdateNotificationsEnabled,
#[clap(name = "proxy.url")]
ProxyUrl,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Parser)]
pub enum StorableConfigField {
#[clap(name = "registry.url")]
RegistryUrl(SetRegistryUrl),
#[clap(name = "registry.token")]
RegistryToken(SetRegistryToken),
#[clap(name = "telemetry.enabled")]
TelemetryEnabled(SetTelemetryEnabled),
#[clap(name = "update-notifications.enabled")]
UpdateNotificationsEnabled(SetUpdateNotificationsEnabled),
#[clap(name = "proxy.url")]
ProxyUrl(SetProxyUrl),
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Parser)]
pub struct SetRegistryUrl {
#[clap(name = "URL")]
pub url: String,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Parser)]
pub struct SetRegistryToken {
#[clap(name = "TOKEN")]
pub token: String,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Parser)]
pub struct SetUpdateNotificationsEnabled {
#[clap(name = "ENABLED")]
pub enabled: BoolString,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct BoolString(pub bool);
impl std::str::FromStr for BoolString {
type Err = ParseBoolError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(bool::from_str(s)?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Parser)]
pub struct SetTelemetryEnabled {
#[clap(name = "ENABLED")]
pub enabled: BoolString,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Parser)]
pub struct SetProxyUrl {
#[clap(name = "URL")]
pub url: String,
}
#[async_trait::async_trait]
impl AsyncCliCommand for Config {
type Output = ();
async fn run_async(self) -> Result<Self::Output, anyhow::Error> {
self.inner_execute()
.await
.context("failed to retrieve the wasmer config".to_string())
}
}
impl Config {
async fn inner_execute(&self) -> Result<()> {
if let Some(s) = self.set.as_ref() {
return s.execute(&self.env).await;
}
let flags = &self.flags;
let prefix = self.env.dir();
let prefixdir = prefix.display().to_string();
let bindir = prefix.join("bin").display().to_string();
let includedir = prefix.join("include").display().to_string();
let libdir = prefix.join("lib").display().to_string();
let cflags = format!("-I{includedir}");
let libs = format!("-L{libdir} -lwasmer");
if flags.pkg_config {
println!("prefix={prefixdir}");
println!("exec_prefix={bindir}");
println!("includedir={includedir}");
println!("libdir={libdir}");
println!();
println!("Name: wasmer");
println!("Description: The Wasmer library for running WebAssembly");
println!("Version: {VERSION}");
println!("Cflags: {cflags}");
println!("Libs: {libs}");
return Ok(());
}
if flags.prefix {
println!("{prefixdir}");
}
if flags.bindir {
println!("{bindir}");
}
if flags.includedir {
println!("{includedir}");
}
if flags.libdir {
println!("{libdir}");
}
if flags.libs {
println!("{libs}");
}
if flags.cflags {
println!("{cflags}");
}
if flags.config_path {
let path = WasmerConfig::get_file_location(self.env.dir());
println!("{}", path.display());
}
Ok(())
}
}
impl GetOrSet {
async 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 {
RetrievableConfigField::RegistryUrl => {
println!("{}", config.registry.get_current_registry());
}
RetrievableConfigField::RegistryToken => {
if let Some(s) = config
.registry
.get_login_token_for_registry(&config.registry.get_current_registry())
{
println!("{s}");
}
}
RetrievableConfigField::TelemetryEnabled => {
println!("{:?}", config.telemetry_enabled);
}
RetrievableConfigField::UpdateNotificationsEnabled => {
println!("{:?}", config.update_notifications_enabled);
}
RetrievableConfigField::ProxyUrl => {
if let Some(s) = config.proxy.url.as_ref() {
println!("{s}");
} else {
println!("none");
}
}
},
GetOrSet::Set(s) => {
match s {
StorableConfigField::RegistryUrl(s) => {
config.registry.set_current_registry(&s.url).await;
let current_registry = config.registry.get_current_registry();
if let Ok(client) = env.client() {
if let Some(u) =
wasmer_backend_api::query::current_user(&client).await?
{
println!(
"Successfully logged into registry {current_registry:?} as user {u:?}"
);
}
}
}
StorableConfigField::RegistryToken(t) => {
config.registry.set_login_token_for_registry(
&config.registry.get_current_registry(),
&t.token,
UpdateRegistry::LeaveAsIs,
);
}
StorableConfigField::TelemetryEnabled(t) => {
config.telemetry_enabled = t.enabled.0;
}
StorableConfigField::ProxyUrl(p) => {
if p.url == "none" || p.url.is_empty() {
config.proxy.url = None;
} else {
config.proxy.url = Some(p.url.clone());
}
}
StorableConfigField::UpdateNotificationsEnabled(u) => {
config.update_notifications_enabled = u.enabled.0;
}
}
config
.save(config_file)
.with_context(|| anyhow::anyhow!("could not save config file"))?;
}
}
Ok(())
}
}