Skip to content

Commit

Permalink
Add setting.
Browse files Browse the repository at this point in the history
  • Loading branch information
milesj committed Nov 14, 2023
1 parent fcb53fb commit d32430c
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 37 deletions.
10 changes: 10 additions & 0 deletions crates/core/src/user_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ use warpgate::{HttpOptions, Id, PluginLocator};

pub const USER_CONFIG_NAME: &str = "config.toml";

#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "kebab-case")]
pub enum DetectStrategy {
#[default]
FirstAvailable,
PreferPrototools,
}

#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "kebab-case")]
pub enum PinType {
Expand All @@ -22,6 +30,7 @@ pub enum PinType {
pub struct UserConfig {
pub auto_clean: bool,
pub auto_install: bool,
pub detect_strategy: DetectStrategy,
pub node_intercept_globals: bool,
pub pin_latest: Option<PinType>,
pub http: HttpOptions,
Expand Down Expand Up @@ -93,6 +102,7 @@ impl Default for UserConfig {
Self {
auto_clean: from_var("PROTO_AUTO_CLEAN", false),
auto_install: from_var("PROTO_AUTO_INSTALL", false),
detect_strategy: DetectStrategy::default(),
http: HttpOptions::default(),
node_intercept_globals: from_var("PROTO_NODE_INTERCEPT_GLOBALS", true),
pin_latest: None,
Expand Down
153 changes: 116 additions & 37 deletions crates/core/src/version_detector.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,117 @@
use crate::error::ProtoError;
use crate::tool::Tool;
use crate::tools_config::ToolsConfig;
use crate::user_config::DetectStrategy;
use std::{env, path::Path};
use tracing::{debug, trace};
use version_spec::*;

async fn detect_version_first_available(
tool: &Tool,
start_dir: &Path,
end_dir: &Path,
) -> miette::Result<Option<UnresolvedVersionSpec>> {
let mut current_dir: Option<&Path> = Some(&start_dir);

while let Some(dir) = current_dir {
trace!(
tool = tool.id.as_str(),
dir = ?dir,
"Checking directory",
);

let config = ToolsConfig::load_from(dir)?;

if let Some(version) = config.tools.get(&tool.id) {
debug!(
tool = tool.id.as_str(),
version = version.to_string(),
file = ?config.path,
"Detected version from .prototools file",
);

return Ok(Some(version.to_owned()));
}

if let Some(version) = tool.detect_version_from(dir).await? {
debug!(
tool = tool.id.as_str(),
version = version.to_string(),
"Detected version from tool's ecosystem"
);

return Ok(Some(version));
}

if dir == end_dir {
break;
}

current_dir = dir.parent();
}

Ok(None)
}

async fn detect_version_prefer_prototools(
tool: &Tool,
start_dir: &Path,
end_dir: &Path,
) -> miette::Result<Option<UnresolvedVersionSpec>> {
let mut config_version = None;
let mut config_path = None;
let mut ecosystem_version = None;
let mut current_dir: Option<&Path> = Some(&start_dir);

while let Some(dir) = current_dir {
trace!(
tool = tool.id.as_str(),
dir = ?dir,
"Checking directory",
);

if config_version.is_none() {
let mut config = ToolsConfig::load_from(dir)?;

config_version = config.tools.remove(&tool.id);
config_path = Some(config.path);
}

if ecosystem_version.is_none() {
ecosystem_version = tool.detect_version_from(dir).await?;
}

if dir == end_dir {
break;
}

current_dir = dir.parent();
}

if let Some(version) = config_version {
debug!(
tool = tool.id.as_str(),
version = version.to_string(),
file = ?config_path.unwrap(),
"Detected version from .prototools file",
);

return Ok(Some(version.to_owned()));
}

if let Some(version) = ecosystem_version {
debug!(
tool = tool.id.as_str(),
version = version.to_string(),
"Detected version from tool's ecosystem"
);

return Ok(Some(version));
}

Ok(None)
}

pub async fn detect_version(
tool: &Tool,
forced_version: Option<UnresolvedVersionSpec>,
Expand Down Expand Up @@ -45,46 +152,18 @@ pub async fn detect_version(

// Traverse upwards and attempt to detect a local version
if let Ok(working_dir) = env::current_dir() {
let mut current_dir: Option<&Path> = Some(&working_dir);

while let Some(dir) = current_dir {
trace!(
tool = tool.id.as_str(),
dir = ?dir,
"Checking directory",
);

// Detect from our config file
let config = ToolsConfig::load_from(dir)?;

if let Some(local_version) = config.tools.get(&tool.id) {
debug!(
tool = tool.id.as_str(),
version = local_version.to_string(),
file = ?config.path,
"Detected version from .prototools file",
);

return Ok(local_version.to_owned());
let user_config = tool.proto.load_user_config()?;
let detected_version = match user_config.detect_strategy {
DetectStrategy::FirstAvailable => {
detect_version_first_available(tool, &working_dir, &tool.proto.home).await?
}

// Detect using the tool
if let Some(detected_version) = tool.detect_version_from(dir).await? {
debug!(
tool = tool.id.as_str(),
version = detected_version.to_string(),
"Detected version from tool's ecosystem"
);

return Ok(detected_version);
}

// Don't traverse passed the home directory
if dir == tool.proto.home {
break;
DetectStrategy::PreferPrototools => {
detect_version_prefer_prototools(tool, &working_dir, &tool.proto.home).await?
}
};

current_dir = dir.parent();
if let Some(version) = detected_version {
return Ok(version);
}
}

Expand Down

0 comments on commit d32430c

Please sign in to comment.