From b62fed7e5152becb743ae9c598a6f91301df0c85 Mon Sep 17 00:00:00 2001 From: jdx <216188+jdx@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:54:19 -0600 Subject: [PATCH] use rtx-versions.jdx.dev to fetch remote versions (#1136) This should improve performance a tad and will also make rtx work better in cases where it does not have GITHUB_API_TOKEN set and is rate-limited on GitHub --- .idea/inspectionProfiles/Project_Default.xml | 31 ++++++++++++++++ src/plugins/core/bun.rs | 9 +++-- src/plugins/core/deno.rs | 9 +++-- src/plugins/core/go.rs | 4 ++ src/plugins/core/java.rs | 4 ++ src/plugins/core/mod.rs | 14 ++++++- src/plugins/core/python.rs | 4 ++ src/plugins/core/ruby.rs | 4 ++ src/plugins/external_plugin.rs | 39 +++++++++++++++++++- src/plugins/mod.rs | 7 +++- 10 files changed, 115 insertions(+), 10 deletions(-) diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 64d6d1127..7a8cf6a2c 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -6,5 +6,36 @@ + + + \ No newline at end of file diff --git a/src/plugins/core/bun.rs b/src/plugins/core/bun.rs index f544be47f..e1b0b8f7c 100644 --- a/src/plugins/core/bun.rs +++ b/src/plugins/core/bun.rs @@ -10,7 +10,7 @@ use crate::config::Settings; use crate::github::GithubRelease; use crate::install_context::InstallContext; use crate::plugins::core::CorePlugin; -use crate::plugins::Plugin; +use crate::plugins::{Plugin, HTTP}; use crate::toolset::{ToolVersion, ToolVersionRequest}; use crate::ui::progress_report::ProgressReport; use crate::{file, http}; @@ -27,9 +27,12 @@ impl BunPlugin { } fn fetch_remote_versions(&self) -> Result> { - let http = http::Client::new()?; + match self.core.fetch_remote_versions_from_rtx() { + Ok(versions) => return Ok(versions), + Err(e) => warn!("failed to fetch remote versions: {}", e), + } let releases: Vec = - http.json("https://api.github.com/repos/oven-sh/bun/releases?per_page=100")?; + HTTP.json("https://api.github.com/repos/oven-sh/bun/releases?per_page=100")?; let versions = releases .into_iter() .map(|r| r.tag_name) diff --git a/src/plugins/core/deno.rs b/src/plugins/core/deno.rs index c4129a92b..59ce2e62a 100644 --- a/src/plugins/core/deno.rs +++ b/src/plugins/core/deno.rs @@ -11,7 +11,7 @@ use crate::config::{Config, Settings}; use crate::github::GithubRelease; use crate::install_context::InstallContext; use crate::plugins::core::CorePlugin; -use crate::plugins::Plugin; +use crate::plugins::{Plugin, HTTP}; use crate::toolset::{ToolVersion, ToolVersionRequest, Toolset}; use crate::ui::progress_report::ProgressReport; use crate::{file, http}; @@ -28,9 +28,12 @@ impl DenoPlugin { } fn fetch_remote_versions(&self) -> Result> { - let http = http::Client::new()?; + match self.core.fetch_remote_versions_from_rtx() { + Ok(versions) => return Ok(versions), + Err(e) => warn!("failed to fetch remote versions: {}", e), + } let releases: Vec = - http.json("https://api.github.com/repos/denoland/deno/releases?per_page=100")?; + HTTP.json("https://api.github.com/repos/denoland/deno/releases?per_page=100")?; let versions = releases .into_iter() .map(|r| r.name) diff --git a/src/plugins/core/go.rs b/src/plugins/core/go.rs index c81dad64e..c6d3d6b97 100644 --- a/src/plugins/core/go.rs +++ b/src/plugins/core/go.rs @@ -28,6 +28,10 @@ impl GoPlugin { } fn fetch_remote_versions(&self) -> Result> { + match self.core.fetch_remote_versions_from_rtx() { + Ok(versions) => return Ok(versions), + Err(e) => warn!("failed to fetch remote versions: {}", e), + } CorePlugin::run_fetch_task_with_timeout(move || { let repo = &*env::RTX_GO_REPO; let output = cmd!("git", "ls-remote", "--tags", repo, "go*").read()?; diff --git a/src/plugins/core/java.rs b/src/plugins/core/java.rs index 756a4ae50..72913286b 100644 --- a/src/plugins/core/java.rs +++ b/src/plugins/core/java.rs @@ -77,6 +77,10 @@ impl JavaPlugin { } fn fetch_remote_versions(&self) -> Result> { + match self.core.fetch_remote_versions_from_rtx() { + Ok(versions) => return Ok(versions), + Err(e) => warn!("failed to fetch remote versions: {}", e), + } let versions = self .fetch_java_metadata("ga")? .iter() diff --git a/src/plugins/core/mod.rs b/src/plugins/core/mod.rs index 0cdae088d..65600ac8a 100644 --- a/src/plugins/core/mod.rs +++ b/src/plugins/core/mod.rs @@ -18,7 +18,7 @@ use crate::plugins::core::java::JavaPlugin; use crate::plugins::core::node::NodePlugin; use crate::plugins::core::node_build::NodeBuildPlugin; use crate::plugins::core::ruby::RubyPlugin; -use crate::plugins::{Plugin, PluginName}; +use crate::plugins::{Plugin, PluginName, HTTP}; use crate::timeout::run_with_timeout; use crate::toolset::ToolVersion; use crate::{dirs, env}; @@ -63,6 +63,7 @@ pub static EXPERIMENTAL_CORE_PLUGINS: Lazy = Lazy::new(|| { #[derive(Debug)] pub struct CorePlugin { + pub name: &'static str, pub cache_path: PathBuf, pub remote_version_cache: CacheManager>, } @@ -71,6 +72,7 @@ impl CorePlugin { pub fn new(name: &'static str) -> Self { let cache_path = dirs::CACHE.join(name); Self { + name, remote_version_cache: CacheManager::new(cache_path.join("remote_versions.msgpack.z")) .with_fresh_duration(*env::RTX_FETCH_REMOTE_VERSIONS_CACHE), cache_path, @@ -90,4 +92,14 @@ impl CorePlugin { { run_with_timeout(f, *env::RTX_FETCH_REMOTE_VERSIONS_TIMEOUT) } + + pub fn fetch_remote_versions_from_rtx(&self) -> Result> { + let versions = HTTP + .get_text(format!("http://rtx-versions.jdx.dev/{}", &self.name))? + .lines() + .map(|v| v.trim().to_string()) + .filter(|v| !v.is_empty()) + .collect(); + Ok(versions) + } } diff --git a/src/plugins/core/python.rs b/src/plugins/core/python.rs index 9519d60d2..5aad85aea 100644 --- a/src/plugins/core/python.rs +++ b/src/plugins/core/python.rs @@ -63,6 +63,10 @@ impl PythonPlugin { } fn fetch_remote_versions(&self) -> Result> { + match self.core.fetch_remote_versions_from_rtx() { + Ok(versions) => return Ok(versions), + Err(e) => warn!("failed to fetch remote versions: {}", e), + } self.install_or_update_python_build()?; let python_build_bin = self.python_build_bin(); CorePlugin::run_fetch_task_with_timeout(move || { diff --git a/src/plugins/core/ruby.rs b/src/plugins/core/ruby.rs index e184a67d5..9a5cc645a 100644 --- a/src/plugins/core/ruby.rs +++ b/src/plugins/core/ruby.rs @@ -141,6 +141,10 @@ impl RubyPlugin { } fn fetch_remote_versions(&self) -> Result> { + match self.core.fetch_remote_versions_from_rtx() { + Ok(versions) => return Ok(versions), + Err(e) => warn!("failed to fetch remote versions: {}", e), + } self.update_build_tool()?; let ruby_build_bin = self.ruby_build_bin(); let versions = CorePlugin::run_fetch_task_with_timeout(move || { diff --git a/src/plugins/external_plugin.rs b/src/plugins/external_plugin.rs index 001c35c7d..5cc1f4bba 100644 --- a/src/plugins/external_plugin.rs +++ b/src/plugins/external_plugin.rs @@ -14,6 +14,7 @@ use once_cell::sync::Lazy; use crate::cache::CacheManager; use crate::config::{Config, Settings}; +use crate::default_shorthands::DEFAULT_SHORTHANDS; use crate::env::RTX_FETCH_REMOTE_VERSIONS_TIMEOUT; use crate::env_diff::{EnvDiff, EnvDiffOperation}; use crate::errors::Error::PluginNotInstalled; @@ -24,13 +25,13 @@ use crate::install_context::InstallContext; use crate::plugins::external_plugin_cache::ExternalPluginCache; use crate::plugins::rtx_plugin_toml::RtxPluginToml; use crate::plugins::Script::{Download, ExecEnv, Install, ParseLegacyFile}; -use crate::plugins::{Plugin, PluginName, PluginType, Script, ScriptManager}; +use crate::plugins::{Plugin, PluginName, PluginType, Script, ScriptManager, HTTP}; use crate::timeout::run_with_timeout; use crate::toolset::{ToolVersion, ToolVersionRequest, Toolset}; use crate::ui::multi_progress_report::MultiProgressReport; use crate::ui::progress_report::ProgressReport; use crate::ui::prompt; -use crate::{dirs, env, file}; +use crate::{dirs, env, file, http}; /// This represents a plugin installed to ~/.local/share/rtx/plugins pub struct ExternalPlugin { @@ -137,7 +138,41 @@ impl ExternalPlugin { Ok(()) } + fn fetch_versions(&self) -> Result>> { + // ensure that we're using a default shorthand plugin + let git = Git::new(self.plugin_path.to_path_buf()); + if git.get_remote_url() + != DEFAULT_SHORTHANDS + .get(self.name.as_str()) + .map(|s| s.to_string()) + { + return Ok(None); + } + let versions = match HTTP.get_text(format!("http://rtx-versions.jdx.dev/{}", self.name)) { + Err(err) if http::error_code(&err) == Some(404) => return Ok(None), + res => res?, + }; + let versions = versions + .lines() + .map(|v| v.trim().to_string()) + .filter(|v| !v.is_empty()) + .collect_vec(); + match versions.is_empty() { + true => Ok(None), + false => Ok(Some(versions)), + } + } + fn fetch_remote_versions(&self, settings: &Settings) -> Result> { + match self.fetch_versions() { + Ok(Some(versions)) => return Ok(versions), + Err(err) => warn!( + "Failed to fetch remote versions for plugin {}: {}", + style(&self.name).cyan().for_stderr(), + err + ), + _ => {} + }; let cmd = self.script_man.cmd(settings, &Script::ListAll); let result = run_with_timeout( move || { diff --git a/src/plugins/mod.rs b/src/plugins/mod.rs index 29b8c0177..4873e4e37 100644 --- a/src/plugins/mod.rs +++ b/src/plugins/mod.rs @@ -9,6 +9,7 @@ use color_eyre::eyre::Result; use console::style; use eyre::WrapErr; use itertools::Itertools; +use once_cell::sync::Lazy; use regex::Regex; use versions::Versioning; @@ -16,6 +17,7 @@ pub use external_plugin::ExternalPlugin; pub use script_manager::{Script, ScriptManager}; use crate::config::{Config, Settings}; +use crate::env::RTX_FETCH_REMOTE_VERSIONS_TIMEOUT; use crate::file::{display_path, remove_all, remove_all_with_warning}; use crate::install_context::InstallContext; use crate::lock_file::LockFile; @@ -23,7 +25,7 @@ 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::{ProgressReport, PROG_TEMPLATE}; -use crate::{dirs, file}; +use crate::{dirs, file, http}; pub mod core; mod external_plugin; @@ -33,6 +35,9 @@ mod script_manager; pub type PluginName = String; +pub static HTTP: Lazy = + Lazy::new(|| http::Client::new_with_timeout(*RTX_FETCH_REMOTE_VERSIONS_TIMEOUT).unwrap()); + pub trait Plugin: Debug + Send + Sync { fn name(&self) -> &str; fn get_type(&self) -> PluginType {