From 10878f22cb116a8140404d1880e352d97837e459 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 15 Jul 2024 09:49:38 +1000 Subject: [PATCH 1/2] Search for envs using user provided conda exe --- crates/pet-conda/src/environment_locations.rs | 45 +++++++++++++++++-- crates/pet-conda/src/lib.rs | 25 ++++++++++- 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/crates/pet-conda/src/environment_locations.rs b/crates/pet-conda/src/environment_locations.rs index f3aaac1a..a263d5e2 100644 --- a/crates/pet-conda/src/environment_locations.rs +++ b/crates/pet-conda/src/environment_locations.rs @@ -17,14 +17,17 @@ use std::{ const APP_NAME: &str = "conda"; -pub fn get_conda_environment_paths(env_vars: &EnvVariables) -> Vec { +pub fn get_conda_environment_paths( + env_vars: &EnvVariables, + conda_executable: &Option, +) -> Vec { let mut env_paths = thread::scope(|s| { let mut envs = vec![]; for thread in [ s.spawn(|| get_conda_envs_from_environment_txt(env_vars)), s.spawn(|| get_conda_environment_paths_from_conda_rc(env_vars)), s.spawn(|| get_conda_environment_paths_from_known_paths(env_vars)), - s.spawn(|| get_known_conda_install_locations(env_vars)), + s.spawn(|| get_known_conda_install_locations(env_vars, conda_executable)), ] { if let Ok(mut env_paths) = thread.join() { envs.append(&mut env_paths); @@ -253,7 +256,10 @@ pub fn get_known_conda_install_locations(env_vars: &EnvVariables) -> Vec Vec { +pub fn get_known_conda_install_locations( + env_vars: &EnvVariables, + conda_executable: &Option, +) -> Vec { let mut known_paths = vec![]; let home_value = env_vars.clone().home.unwrap_or_default(); let directories_to_look_in = [ @@ -294,8 +300,41 @@ pub fn get_known_conda_install_locations(env_vars: &EnvVariables) -> Vec) -> Option { + if let Some(conda_executable) = conda_executable { + if conda_executable.is_file() { + if let Some(conda_dir) = conda_executable.parent() { + // Possible exe is in the install (root prefix) directory. + if is_conda_env(conda_dir) { + return Some(conda_dir.to_path_buf()); + } else if let Some(conda_dir) = conda_dir.parent() { + // Possible the exe is in the `bin` or `Scripts` directory. + if is_conda_env(conda_dir) { + return Some(conda_dir.to_path_buf()); + } + } + } + } else { + let conda_dir = conda_executable.clone(); + // Possible exe is in the install (root prefix) directory. + if is_conda_env(&conda_dir) { + return Some(conda_dir.to_path_buf()); + } else if let Some(conda_dir) = conda_dir.parent() { + // Possible the exe is in the `bin` or `Scripts` directory. + if is_conda_env(conda_dir) { + return Some(conda_dir.to_path_buf()); + } + } + } + } + None +} diff --git a/crates/pet-conda/src/lib.rs b/crates/pet-conda/src/lib.rs index 89d42aa3..e9531508 100644 --- a/crates/pet-conda/src/lib.rs +++ b/crates/pet-conda/src/lib.rs @@ -4,7 +4,8 @@ use conda_info::CondaInfo; use env_variables::EnvVariables; use environment_locations::{ - get_conda_environment_paths, get_conda_envs_from_environment_txt, get_environments, + get_conda_dir_from_exe, get_conda_environment_paths, get_conda_envs_from_environment_txt, + get_environments, }; use environments::{get_conda_environment_info, CondaEnvironment}; use log::error; @@ -15,6 +16,7 @@ use pet_core::{ reporter::Reporter, Locator, }; +use pet_fs::path::norm_case; use pet_python_utils::env::PythonEnv; use serde::{Deserialize, Serialize}; use std::{ @@ -54,6 +56,7 @@ pub struct CondaTelemetryInfo { pub env_dirs: Vec, pub environments_txt: Option, pub environments_txt_exists: Option, + pub user_provided_env_found: Option, pub environments_from_txt: Vec, } @@ -61,6 +64,7 @@ pub struct Conda { pub environments: Arc>>, pub managers: Arc>>, pub env_vars: EnvVariables, + conda_executable: Arc>>, } impl Conda { @@ -69,6 +73,7 @@ impl Conda { environments: Arc::new(Mutex::new(HashMap::new())), managers: Arc::new(Mutex::new(HashMap::new())), env_vars: EnvVariables::from(env), + conda_executable: Arc::new(Mutex::new(None)), } } fn clear(&self) { @@ -127,10 +132,19 @@ impl CondaLocator for Conda { environments_txt = Some(file); } + let conda_exe = &self.conda_executable.lock().unwrap().clone(); + let envs_found = get_conda_environment_paths(&self.env_vars, conda_exe); + let mut user_provided_env_found = None; + if let Some(conda_dir) = get_conda_dir_from_exe(conda_exe) { + let conda_dir = norm_case(conda_dir); + user_provided_env_found = Some(envs_found.contains(&conda_dir)); + } + CondaTelemetryInfo { can_spawn_conda, conda_rcs, env_dirs, + user_provided_env_found, environments_txt, environments_txt_exists, environments_from_txt: get_conda_envs_from_environment_txt(&self.env_vars), @@ -192,6 +206,12 @@ impl Locator for Conda { fn get_name(&self) -> &'static str { "Conda" // Do not change this name, as this is used in telemetry. } + fn configure(&self, config: &pet_core::Configuration) { + if let Some(ref conda_exe) = config.conda_executable { + let mut conda_executable = self.conda_executable.lock().unwrap(); + conda_executable.replace(conda_exe.clone()); + } + } fn supported_categories(&self) -> Vec { vec![PythonEnvironmentKind::Conda] } @@ -262,9 +282,10 @@ impl Locator for Conda { self.clear(); let env_vars = self.env_vars.clone(); + let executable = self.conda_executable.lock().unwrap().clone(); thread::scope(|s| { // 1. Get a list of all know conda environments file paths - let possible_conda_envs = get_conda_environment_paths(&env_vars); + let possible_conda_envs = get_conda_environment_paths(&env_vars, &executable); for path in possible_conda_envs { s.spawn(move || { // 2. Get the details of the conda environment From fac318b4f9e362f061aa18f2d2d69a604d692b34 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 15 Jul 2024 09:59:54 +1000 Subject: [PATCH 2/2] fixes --- crates/pet-conda/src/environment_locations.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/pet-conda/src/environment_locations.rs b/crates/pet-conda/src/environment_locations.rs index a263d5e2..8f67c2c5 100644 --- a/crates/pet-conda/src/environment_locations.rs +++ b/crates/pet-conda/src/environment_locations.rs @@ -191,7 +191,10 @@ pub fn get_conda_envs_from_environment_txt(env_vars: &EnvVariables) -> Vec Vec { +pub fn get_known_conda_install_locations( + env_vars: &EnvVariables, + conda_executable: &Option, +) -> Vec { use pet_fs::path::norm_case; let user_profile = env_vars.userprofile.clone().unwrap_or_default(); @@ -249,6 +252,9 @@ pub fn get_known_conda_install_locations(env_vars: &EnvVariables) -> Vec