use std::sync::Arc;
use console::style;
use eyre::{Result, WrapErr, eyre};
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;
#[derive(Debug, clap::Args)]
#[clap(verbatim_doc_comment, visible_aliases = ["up", "upgrade"], after_long_help = AFTER_LONG_HELP)]
pub struct Update {
#[clap()]
plugin: Option<Vec<String>>,
#[clap(long, short, verbatim_doc_comment)]
jobs: Option<usize>,
}
impl Update {
pub 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<Result<()>> = JoinSet::new();
let semaphore = Arc::new(Semaphore::new(self.jobs.unwrap_or(settings.jobs)));
for (short, ref_) in plugins {
let permit = semaphore.clone().acquire_owned().await?;
jset.spawn(async move {
let _permit = permit;
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
.wrap_err_with(|| format!("[{plugin}] plugin update"))?;
Ok(())
});
}
while let Some(result) = jset.join_next().await {
match result {
Ok(Ok(())) => {}
Ok(Err(e)) => {
return Err(e);
}
Err(e) => {
return Err(eyre!(e));
}
}
}
Ok(())
}
}
static AFTER_LONG_HELP: &str = color_print::cstr!(
r#"<bold><underline>Examples:</underline></bold>
$ <bold>mise plugins update</bold> # update all plugins
$ <bold>mise plugins update cmake</bold> # update only cmake
$ <bold>mise plugins update cmake#beta</bold> # specify a ref
"#
);