use color_eyre::eyre::Result;
use itertools::Itertools;
use std::collections::BTreeMap;
use crate::cli::args::tool::ToolArg;
use crate::config::Config;
use crate::env;
use crate::toolset::{ToolSource, ToolVersionRequest, Toolset};
use crate::ui::multi_progress_report::MultiProgressReport;
#[derive(Debug, Default)]
pub struct ToolsetBuilder {
args: Vec<ToolArg>,
install_missing: bool,
latest_versions: bool,
global_only: bool,
tool_filter: Option<Vec<String>>,
}
impl ToolsetBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn with_args(mut self, args: &[ToolArg]) -> Self {
self.args = args.to_vec();
self
}
pub fn with_install_missing(mut self) -> Self {
self.install_missing = true;
self
}
pub fn with_latest_versions(mut self) -> Self {
self.latest_versions = true;
self
}
pub fn with_global_only(mut self, global_only: bool) -> Self {
self.global_only = global_only;
self
}
pub fn with_tools(mut self, tools: &[&str]) -> Self {
self.tool_filter = Some(tools.iter().map(|s| s.to_string()).collect());
self
}
pub fn build(self, config: &mut Config) -> Result<Toolset> {
let mut toolset = Toolset {
latest_versions: self.latest_versions,
disable_tools: config.settings.disable_tools.clone(),
..Default::default()
};
self.load_config_files(config, &mut toolset);
self.load_runtime_env(&mut toolset, env::vars().collect());
self.load_runtime_args(&mut toolset);
if let Some(tools) = self.tool_filter {
toolset.versions.retain(|p, _| tools.contains(p));
}
toolset.resolve(config);
if self.install_missing {
let mpr = MultiProgressReport::new(config.show_progress_bars());
toolset.install_missing(config, mpr)?;
}
debug!("{}", toolset);
Ok(toolset)
}
fn load_config_files(&self, config: &Config, ts: &mut Toolset) {
for cf in config.config_files.values().rev() {
if self.global_only && !cf.is_global() {
return;
}
ts.merge(cf.to_toolset());
}
}
fn load_runtime_env(&self, ts: &mut Toolset, env: BTreeMap<String, String>) {
if self.global_only {
return;
}
for (k, v) in env {
if k.starts_with("RTX_") && k.ends_with("_VERSION") && k != "RTX_VERSION" {
let plugin_name = k[4..k.len() - 8].to_lowercase();
if plugin_name == "install" {
continue;
}
let source = ToolSource::Environment(k, v.clone());
let mut env_ts = Toolset::new(source);
for v in v.split_whitespace() {
let tvr = ToolVersionRequest::new(plugin_name.clone(), v);
env_ts.add_version(tvr, Default::default());
}
ts.merge(&env_ts);
}
}
}
fn load_runtime_args(&self, ts: &mut Toolset) {
if self.global_only {
return;
}
for (_, args) in self.args.iter().into_group_map_by(|arg| arg.plugin.clone()) {
let mut arg_ts = Toolset::new(ToolSource::Argument);
for arg in args {
if let Some(tvr) = &arg.tvr {
arg_ts.add_version(tvr.clone(), Default::default());
}
}
ts.merge(&arg_ts);
}
}
}