Skip to content

Commit

Permalink
plugin-update: update in parallel (#1186)
Browse files Browse the repository at this point in the history
* plugin-update: update in parallel

* lint

* Commit from GitHub Actions (test)

* lint

---------

Co-authored-by: rtx[bot] <[email protected]>
  • Loading branch information
jdx and mise-en-dev authored Dec 14, 2023
1 parent f4b8c34 commit c778555
Show file tree
Hide file tree
Showing 17 changed files with 129 additions and 151 deletions.
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ v20.0.0
- [`rtx plugins ls [OPTIONS]`](#rtx-plugins-ls-options)
- [`rtx plugins ls-remote [OPTIONS]`](#rtx-plugins-ls-remote-options)
- [`rtx plugins uninstall [OPTIONS] [PLUGIN]...`](#rtx-plugins-uninstall-options-plugin)
- [`rtx plugins update [PLUGIN]...`](#rtx-plugins-update-plugin)
- [`rtx plugins update [OPTIONS] [PLUGIN]...`](#rtx-plugins-update-options-plugin)
- [`rtx prune [OPTIONS] [PLUGIN]...`](#rtx-prune-options-plugin)
- [`rtx reshim`](#rtx-reshim)
- [`rtx self-update [OPTIONS] [VERSION]`](#rtx-self-update-options-version)
Expand Down Expand Up @@ -2386,19 +2386,24 @@ Examples:
$ rtx uninstall node
```

### `rtx plugins update [PLUGIN]...`
### `rtx plugins update [OPTIONS] [PLUGIN]...`

```text
Updates a plugin to the latest version
note: this updates the plugin itself, not the runtime versions
Usage: plugins update [PLUGIN]...
Usage: plugins update [OPTIONS] [PLUGIN]...
Arguments:
[PLUGIN]...
Plugin(s) to update
Options:
-j, --jobs <JOBS>
Number of jobs to run in parallel
Default: 4
Examples:
$ rtx plugins update # update all plugins
$ rtx plugins update node # update only node
Expand Down
1 change: 1 addition & 0 deletions completions/_rtx
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,7 @@ __rtx_plugins_uninstall_cmd() {
__rtx_plugins_update_cmd() {
_arguments -s -S \
'*::plugin:__rtx_plugins' \
'(-j --jobs)'{-j,--jobs}'=[Number of jobs to run in parallel]:jobs:' \
'(-q --quiet)'{-q,--quiet}'[Suppress output]' \
'*'{-v,--verbose}'[Show extra output (use -vv for even more)]' \
'(-y --yes)'{-y,--yes}'[Answer yes to all prompts]'
Expand Down
10 changes: 9 additions & 1 deletion completions/rtx.bash
Original file line number Diff line number Diff line change
Expand Up @@ -2527,12 +2527,20 @@ _rtx() {
return 0
;;
rtx__plugins__update)
opts="-a -q -v -y -h --all --debug --log-level --trace --quiet --verbose --yes --help [PLUGIN]..."
opts="-j -q -v -y -h --jobs --debug --log-level --trace --quiet --verbose --yes --help [PLUGIN]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
--jobs)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
-j)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--log-level)
COMPREPLY=($(compgen -W "error warn info debug trace" -- "${cur}"))
return 0
Expand Down
1 change: 1 addition & 0 deletions completions/rtx.fish
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ complete -kxc rtx -n "$fssf plugins; and $fssf uninstall" -a "(__rtx_plugins)" -
complete -kxc rtx -n "$fssf plugins; and $fssf uninstall" -s p -l purge -d 'Also remove the plugin'\''s installs, downloads, and cache'
# plugins update
complete -kxc rtx -n "$fssf plugins; and $fssf update" -s j -l jobs -d 'Number of jobs to run in parallel'
complete -kxc rtx -n "$fssf plugins; and $fssf update" -a "(__rtx_plugins)" -d 'Plugin(s) to update'
Expand Down
3 changes: 1 addition & 2 deletions src/cli/plugins/uninstall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ impl PluginsUninstall {
) -> Result<()> {
match config.get_or_create_plugin(plugin_name) {
plugin if plugin.is_installed() => {
let mut pr = mpr.add();
plugin.decorate_progress_bar(pr.as_mut(), None);
let pr = mpr.add(&style(plugin.name()).blue().for_stderr().to_string());
plugin.uninstall(pr.as_ref())?;
if self.purge {
plugin.purge(pr.as_ref())?;
Expand Down
31 changes: 22 additions & 9 deletions src/cli/plugins/update.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use color_eyre::eyre::Result;
use console::style;
use rayon::prelude::*;

use crate::config::Config;
use crate::config::{Config, Settings};

use crate::plugins::{unalias_plugin, PluginName};
use crate::ui::multi_progress_report::MultiProgressReport;

/// Updates a plugin to the latest version
///
Expand All @@ -14,9 +17,10 @@ pub struct Update {
#[clap()]
plugin: Option<Vec<PluginName>>,

/// Update all plugins
#[clap(long, short = 'a', conflicts_with = "plugin", hide = true)]
all: bool,
/// Number of jobs to run in parallel
/// Default: 4
#[clap(long, short, verbatim_doc_comment)]
jobs: Option<usize>,
}

impl Update {
Expand All @@ -41,11 +45,20 @@ impl Update {
.collect::<Vec<_>>(),
};

for (plugin, ref_) in plugins {
rtxprintln!("updating plugin {plugin}");
plugin.update(ref_)?;
}
Ok(())
// let queue = Mutex::new(plugins);
let settings = Settings::try_get()?;
let mpr = MultiProgressReport::new();
rayon::ThreadPoolBuilder::new()
.num_threads(self.jobs.unwrap_or(settings.jobs))
.build()?
.install(|| {
plugins.into_par_iter().for_each(|(plugin, ref_)| {
let prefix = format!("plugin:{}", style(plugin.name()).blue().for_stderr());
let pr = mpr.add(&prefix);
plugin.update(pr.as_ref(), ref_).unwrap();
});
Ok(())
})
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/cli/prune.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ impl Prune {
let settings = Settings::try_get()?;
let mpr = MultiProgressReport::new();
for (p, tv) in to_delete {
let mut pr = mpr.add();
let mut prefix = format!("{}", style(&tv).cyan().for_stderr());
if self.dry_run {
pr.set_prefix(&format!("{} {} ", pr.prefix(), style("[dryrun]").bold()));
prefix = format!("{} {} ", prefix, style("[dryrun]").bold());
}
let pr = mpr.add(&prefix);
if self.dry_run || settings.yes || prompt::confirm(&format!("remove {} ?", &tv))? {
p.decorate_progress_bar(pr.as_mut(), Some(&tv));
p.uninstall_version(&tv, pr.as_ref(), self.dry_run)?;
pr.finish();
}
Expand Down
4 changes: 2 additions & 2 deletions src/cli/uninstall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ impl Uninstall {
continue;
}

let mut pr = mpr.add();
plugin.decorate_progress_bar(pr.as_mut(), Some(&tv));
let prefix = format!("{}", style(&tv).cyan().for_stderr());
let pr = mpr.add(&prefix);
if let Err(err) = plugin.uninstall_version(&tv, pr.as_ref(), self.dry_run) {
pr.error(err.to_string());
return Err(eyre!(err).wrap_err(format!("failed to uninstall {tv}")));
Expand Down
9 changes: 5 additions & 4 deletions src/cli/upgrade.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use console::style;
use std::collections::HashSet;
use std::sync::Arc;

Expand Down Expand Up @@ -94,8 +95,9 @@ impl Upgrade {
};
ts.install_versions(config, new_versions, &mpr, &opts)?;
for (tool, tv) in to_remove {
let mut pr = mpr.add();
self.uninstall_old_version(tool.clone(), &tv, pr.as_mut())?;
let prefix = format!("{}", style(&tv).cyan().for_stderr());
let pr = mpr.add(&prefix);
self.uninstall_old_version(tool.clone(), &tv, pr.as_ref())?;
}

let ts = ToolsetBuilder::new().with_args(&self.tool).build(config)?;
Expand All @@ -108,9 +110,8 @@ impl Upgrade {
&self,
tool: Arc<dyn Plugin>,
tv: &ToolVersion,
pr: &mut dyn SingleReport,
pr: &dyn SingleReport,
) -> Result<()> {
tool.decorate_progress_bar(pr, Some(tv));
match tool.uninstall_version(tv, pr, self.dry_run) {
Ok(_) => {
pr.finish();
Expand Down
2 changes: 1 addition & 1 deletion src/config/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl Settings {
if *env::CI {
p.yes = Some(true);
}
if *env::RTX_LOG_LEVEL < LevelFilter::Info {
if *env::RTX_LOG_LEVEL > LevelFilter::Info {
p.verbose = Some(true);
}
for arg in &*env::ARGS.read().unwrap() {
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/core/go.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ impl Plugin for GoPlugin {
Ok(())
}

fn uninstall_version_impl(&self, tv: &ToolVersion) -> Result<()> {
fn uninstall_version_impl(&self, _pr: &dyn SingleReport, tv: &ToolVersion) -> Result<()> {
let gopath = self.gopath(tv);
if gopath.exists() {
cmd!("chmod", "-R", "u+wx", gopath).run()?;
Expand Down
40 changes: 29 additions & 11 deletions src/plugins/external_plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ impl ExternalPlugin {
pr.set_message(format!("checking out {ref_}"));
git.update(Some(ref_.to_string()))?;
}
self.exec_hook(pr, "post-plugin-add")?;

let sha = git.current_sha_short()?;
pr.finish_with_message(format!(
Expand Down Expand Up @@ -366,6 +367,15 @@ impl ExternalPlugin {
.with_env("ASDF_INSTALL_VERSION", install_version);
sm
}

fn exec_hook(&self, pr: &dyn SingleReport, hook: &str) -> Result<()> {
let script = Script::Hook(hook.to_string());
if self.script_man.script_exists(&script) {
pr.set_message(format!("executing {hook} hook"));
self.script_man.run_by_line(&script, pr)?;
}
Ok(())
}
}

fn build_script_man(name: &str, plugin_path: &Path) -> ScriptManager {
Expand Down Expand Up @@ -464,39 +474,46 @@ impl Plugin for ExternalPlugin {
}
let _mpr = MultiProgressReport::new();
let mpr = mpr.unwrap_or(&_mpr);
let mut pr = mpr.add();
self.decorate_progress_bar(pr.as_mut(), None);
let pr = mpr.add(&style(&self.name).blue().for_stderr().to_string());
let _lock = self.get_lock(&self.plugin_path, force)?;
self.install(pr.as_ref())
}

fn update(&self, gitref: Option<String>) -> Result<()> {
fn update(&self, pr: &dyn SingleReport, gitref: Option<String>) -> Result<()> {
let config = Config::get();
let plugin_path = self.plugin_path.to_path_buf();
if plugin_path.is_symlink() {
warn!(
pr.warn(format!(
"Plugin: {} is a symlink, not updating",
style(&self.name).cyan().for_stderr()
);
));
return Ok(());
}
let git = Git::new(plugin_path);
if !git.is_repo() {
warn!(
pr.warn(format!(
"Plugin {} is not a git repository, not updating",
style(&self.name).cyan().for_stderr()
);
));
return Ok(());
}
// TODO: asdf_run_hook "pre_plugin_update"
pr.set_message("updating git repo".into());
let (_pre, _post) = git.update(gitref)?;
// TODO: asdf_run_hook "post_plugin_update"
let sha = git.current_sha_short()?;
let repo_url = self.get_repo_url(&config)?;
self.exec_hook(pr, "post-plugin-update")?;
pr.finish_with_message(format!(
"{repo_url}#{}",
style(&sha).bright().yellow().for_stderr(),
));
Ok(())
}

fn uninstall(&self, pr: &dyn SingleReport) -> Result<()> {
if !self.is_installed() {
return Ok(());
}
self.exec_hook(pr, "pre-plugin-remove")?;
pr.set_message("uninstalling".into());

let rmdir = |dir: &Path| {
Expand Down Expand Up @@ -647,9 +664,10 @@ impl Plugin for ExternalPlugin {
Ok(())
}

fn uninstall_version_impl(&self, tv: &ToolVersion) -> Result<()> {
fn uninstall_version_impl(&self, pr: &dyn SingleReport, tv: &ToolVersion) -> Result<()> {
if self.plugin_path.join("bin/uninstall").exists() {
self.script_man_for_tv(tv).run(&Script::Uninstall)?;
self.script_man_for_tv(tv)
.run_by_line(&Script::Uninstall, pr)?;
}
Ok(())
}
Expand Down
25 changes: 5 additions & 20 deletions src/plugins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::lock_file::LockFile;
use crate::runtime_symlinks::is_runtime_symlink;
use crate::toolset::{ToolVersion, ToolVersionRequest, Toolset};
use crate::ui::multi_progress_report::MultiProgressReport;
use crate::ui::progress_report::{SingleReport, PROG_TEMPLATE};
use crate::ui::progress_report::SingleReport;
use crate::{dirs, file, http};

pub mod core;
Expand Down Expand Up @@ -155,7 +155,7 @@ pub trait Plugin: Debug + Send + Sync {
fn ensure_installed(&self, _mpr: Option<&MultiProgressReport>, _force: bool) -> Result<()> {
Ok(())
}
fn update(&self, _git_ref: Option<String>) -> Result<()> {
fn update(&self, _pr: &dyn SingleReport, _git_ref: Option<String>) -> Result<()> {
Ok(())
}
fn uninstall(&self, _pr: &dyn SingleReport) -> Result<()> {
Expand Down Expand Up @@ -183,7 +183,7 @@ pub trait Plugin: Debug + Send + Sync {
fn execute_external_command(&self, _command: &str, _args: Vec<String>) -> Result<()> {
unimplemented!()
}
fn install_version(&self, mut ctx: InstallContext) -> Result<()> {
fn install_version(&self, ctx: InstallContext) -> Result<()> {
let config = Config::get();
let settings = Settings::try_get()?;
if self.is_version_installed(&ctx.tv) {
Expand All @@ -193,7 +193,6 @@ pub trait Plugin: Debug + Send + Sync {
return Ok(());
}
}
self.decorate_progress_bar(ctx.pr.as_mut(), Some(&ctx.tv));
let _lock = self.get_lock(&ctx.tv.install_path(), ctx.force)?;
self.create_install_dirs(&ctx.tv)?;

Expand Down Expand Up @@ -229,7 +228,7 @@ pub trait Plugin: Debug + Send + Sync {
pr.set_message(format!("uninstall {tv}"));

if !dryrun {
self.uninstall_version_impl(tv)?;
self.uninstall_version_impl(pr, tv)?;
}
let rmdir = |dir: &Path| {
if !dir.exists() {
Expand All @@ -246,7 +245,7 @@ pub trait Plugin: Debug + Send + Sync {
rmdir(&tv.cache_path())?;
Ok(())
}
fn uninstall_version_impl(&self, _tv: &ToolVersion) -> Result<()> {
fn uninstall_version_impl(&self, _pr: &dyn SingleReport, _tv: &ToolVersion) -> Result<()> {
Ok(())
}
fn list_bin_paths(&self, tv: &ToolVersion) -> Result<Vec<PathBuf>> {
Expand Down Expand Up @@ -309,20 +308,6 @@ pub trait Plugin: Debug + Send + Sync {
let _ = remove_all_with_warning(tv.download_path());
}
}
fn decorate_progress_bar(&self, pr: &mut dyn SingleReport, tv: Option<&ToolVersion>) {
pr.set_style(PROG_TEMPLATE.clone());
let tool = match tv {
Some(tv) => tv.to_string(),
None => self.name().to_string(),
};
pr.set_prefix(&format!(
"{} {} ",
style("rtx").dim().for_stderr(),
style(tool).cyan().for_stderr(),
));
pr.enable_steady_tick();
}

fn incomplete_file_path(&self, tv: &ToolVersion) -> PathBuf {
tv.cache_path().join("incomplete")
}
Expand Down
Loading

0 comments on commit c778555

Please sign in to comment.