use std::sync::Arc;
use console::style;
use eyre::Result;
use tokio::{sync::Semaphore, task::JoinSet};
use crate::config::Settings;
use crate::plugins;
use crate::toolset::install_state;
use crate::ui::multi_progress_report::MultiProgressReport;
use super::{PluginTaskNames, PluginTaskResult, join_plugin_tasks, spawn_plugin_task};
#[derive(Debug, usage_rs::Args)]
#[usage(verbatim_doc_comment, visible_aliases = ["up", "upgrade"], example(r###"mise plugins update # update all installed plugins
mise plugins update my-tool # update one Git plugin
mise plugins update my-tool#main # select an upstream ref"###))]
pub(super) struct Update {
#[usage()]
plugin: Option<Vec<String>>,
#[usage(long, short, verbatim_doc_comment)]
jobs: Option<usize>,
}
impl Update {
pub(super) async fn run(self) -> Result<()> {
let plugins: Vec<_> = match self.plugin {
Some(plugins) => plugins
.into_iter()
.map(|p| match p.split_once('#') {
Some((p, ref_)) => (p.to_string(), Some(ref_.to_string())),
None => (p, None),
})
.collect(),
None => install_state::list_plugins()
.keys()
.map(|p| (p.clone(), None))
.collect::<Vec<_>>(),
};
let settings = Settings::try_get()?;
let mut jset: JoinSet<PluginTaskResult> = JoinSet::new();
let mut task_names = PluginTaskNames::new();
let jobs = crate::jobs::resolve(settings.jobs, self.jobs);
let semaphore = Arc::new(Semaphore::new(jobs));
for (short, ref_) in plugins {
let semaphore = semaphore.clone();
let plugin_name = short.clone();
spawn_plugin_task(&mut jset, &mut task_names, plugin_name, async move {
let _permit = semaphore.acquire_owned().await?;
let plugin = plugins::get(&short)?;
let prefix = format!("plugin:{}", style(plugin.name()).blue().for_stderr());
let mpr = MultiProgressReport::get();
let pr = mpr.add(&prefix);
plugin.update(pr.as_ref(), ref_).await?;
Ok(())
});
}
join_plugin_tasks(jset, task_names, "update").await
}
}