use onerom_cli::plugin::{Catalogue, Plugin, Release};
use onerom_cli::{CliFetch, Error, Options};
use onerom_config::fw::FirmwareVersion;
use crate::args::plugin::PluginArgs;
pub async fn cmd_plugin(options: &Options, args: &PluginArgs) -> Result<(), Error> {
let fw_version = resolve_fw_version(options, args)?;
let mut catalogue = Catalogue::fetch(&CliFetch).await?;
let failures = catalogue.load_all_releases_resilient(&CliFetch).await;
let plugins: Vec<&Plugin> = catalogue
.plugins()
.iter()
.filter(|p| args.r#type.is_none_or(|t| p.plugin_type == t))
.collect();
if plugins.is_empty() {
if catalogue.plugins().is_empty() {
println!("No plugins available.");
} else {
println!("No plugins found matching the specified type.");
}
return Ok(());
}
if options.verbose {
match &fw_version {
Some(fw) => println!("Firmware version: {fw}"),
None => println!("Connect a device or use --fw-version to check compatibility."),
}
}
println!("Available plugins ({}):", plugins.len());
for plugin in plugins {
println!("---");
print_plugin(options, plugin, &fw_version, args.all_versions);
}
for (name, error) in &failures {
println!("---");
println!(" {name}: failed to fetch releases: {error}");
}
Ok(())
}
fn print_plugin(
options: &Options,
plugin: &Plugin,
fw_version: &Option<FirmwareVersion>,
all_versions: bool,
) {
let display = plugin.display_name.as_deref().unwrap_or(&plugin.name);
println!("{}/{} - {display}", plugin.plugin_type.short(), plugin.name);
if let Some(desc) = plugin.description.as_deref() {
println!(" {desc}");
}
if plugin.releases.is_empty() {
println!(" No releases available.");
return;
}
let to_show: Vec<&Release> = if all_versions {
plugin.releases.iter().collect()
} else {
plugin.releases.iter().take(1).collect()
};
for release in to_show {
print_release(options, release, fw_version);
}
}
fn print_release(options: &Options, release: &Release, fw_version: &Option<FirmwareVersion>) {
let compat = match fw_version {
Some(fw) if !release.is_compatible(fw) => " - incompatible with selected firmware",
_ => "",
};
let min_fw = if options.verbose {
format!(
" - requires One ROM firmware >= v{}",
release.min_fw_version
)
} else {
String::new()
};
println!(" v{}{min_fw}{compat}", release.version);
}
fn resolve_fw_version(
options: &Options,
args: &PluginArgs,
) -> Result<Option<FirmwareVersion>, Error> {
if let Some(v) = &args.fw_version {
return FirmwareVersion::try_from_str(v).map(Some).map_err(|_| {
Error::InvalidArgument(
"--fw-version".to_string(),
format!("Expected format major.minor.patch (e.g. 0.6.6)\n --fw-version '{v}'"),
)
});
}
if let Some(device) = &options.device
&& let Some(onerom) = &device.onerom
{
return Ok(onerom.version());
}
Ok(None)
}