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 {