Skip to content

Commit 8fb7ab6

Browse files
committed
fix: improve conda environment name retrieval for path-based and external environments
1 parent 7f73e80 commit 8fb7ab6

File tree

1 file changed

+62
-29
lines changed

1 file changed

+62
-29
lines changed

crates/pet-conda/src/environments.rs

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -192,18 +192,25 @@ fn get_conda_env_name(
192192
// E.g. conda env is = <conda install>/envs/<env name>
193193
// Then we can use `<conda install>/bin/conda activate -n <env name>`
194194
//
195-
// Check the history file when:
196-
// 1. conda_dir is known but prefix is not under it (external environment)
197-
// 2. conda_dir is unknown (we need to check history to determine if it's name or path based)
198-
// This ensures path-based environments (created with --prefix) return None for name,
199-
// so activation uses the full path instead of incorrectly trying name-based activation.
200-
let should_check_history = match conda_dir {
201-
Some(dir) => !prefix.starts_with(dir),
202-
None => true,
203-
};
204-
205-
if should_check_history {
206-
name = get_conda_env_name_from_history_file(env_path, prefix);
195+
// Handle three cases:
196+
// 1. conda_dir known, prefix is under it → name-based activation works, return folder name
197+
// 2. conda_dir known, prefix NOT under it → external env, check history to distinguish -n vs -p
198+
// 3. conda_dir unknown → can't do name-based activation without knowing conda installation,
199+
// return None so activation uses full path (fixes issue #329 for path-based envs)
200+
match conda_dir {
201+
Some(dir) => {
202+
if !prefix.starts_with(dir) {
203+
// External environment - check history to see if created with -n or -p
204+
name = get_conda_env_name_from_history_file(env_path, prefix);
205+
}
206+
// else: env is under conda_dir/envs/, name-based activation works
207+
}
208+
None => {
209+
// No known conda installation directory
210+
// Name-based activation requires knowing which conda to use, so return None
211+
// This ensures path-based activation is used (correct for --prefix envs too)
212+
name = None;
213+
}
207214
}
208215

209216
name
@@ -440,13 +447,37 @@ mod tests {
440447
));
441448
}
442449

443-
/// Test that path-based conda environments (created with --prefix) return None for name
444-
/// when conda_dir is unknown. This ensures VS Code uses path-based activation.
445-
/// Regression test for https://github.com/microsoft/python-environment-tools/issues/329
450+
/// Test that when conda_dir is unknown, we return None for name.
451+
/// This is correct because name-based activation requires knowing which conda installation
452+
/// to use. Without conda_dir, activation must use the full path.
453+
/// This also fixes issue #329 where path-based envs incorrectly got a name.
446454
#[test]
447-
fn path_based_env_returns_none_name_when_conda_dir_unknown() {
448-
// Create a temp directory structure simulating a path-based conda env
449-
let temp_dir = std::env::temp_dir().join("pet_test_path_based_env");
455+
fn env_returns_none_name_when_conda_dir_unknown() {
456+
// Create a temp directory structure simulating a conda env
457+
let temp_dir = std::env::temp_dir().join("pet_test_conda_dir_unknown");
458+
let conda_meta_dir = temp_dir.join("myenv").join("conda-meta");
459+
std::fs::create_dir_all(&conda_meta_dir).unwrap();
460+
461+
let env_path = temp_dir.join("myenv");
462+
463+
// When conda_dir is None, name should be None (can't do named activation)
464+
let name = get_conda_env_name(&env_path, &env_path, &None);
465+
assert!(
466+
name.is_none(),
467+
"When conda_dir is unknown, name should be None for path-based activation, got {:?}",
468+
name
469+
);
470+
471+
// Cleanup
472+
let _ = std::fs::remove_dir_all(&temp_dir);
473+
}
474+
475+
/// Test that external environments (not under conda_dir) created with --prefix
476+
/// return None for name, so activation uses path instead of name.
477+
#[test]
478+
fn external_path_based_env_returns_none_name() {
479+
// Create a temp directory simulating an external path-based conda env
480+
let temp_dir = std::env::temp_dir().join("pet_test_external_path_env");
450481
let conda_meta_dir = temp_dir.join(".conda").join("conda-meta");
451482
std::fs::create_dir_all(&conda_meta_dir).unwrap();
452483

@@ -459,25 +490,26 @@ mod tests {
459490
.unwrap();
460491

461492
let env_path = temp_dir.join(".conda");
493+
// conda_dir is known but env is NOT under it (external environment)
494+
let conda_dir = Some(std::path::PathBuf::from("/some/other/conda"));
462495

463-
// When conda_dir is None and env was created with --prefix, name should be None
464-
let name = get_conda_env_name(&env_path, &env_path, &None);
496+
let name = get_conda_env_name(&env_path, &env_path, &conda_dir);
465497
assert!(
466498
name.is_none(),
467-
"Path-based env should return None for name, got {:?}",
499+
"Path-based external env should return None for name, got {:?}",
468500
name
469501
);
470502

471503
// Cleanup
472504
let _ = std::fs::remove_dir_all(&temp_dir);
473505
}
474506

475-
/// Test that name-based conda environments (created with -n) return the name
476-
/// even when conda_dir is unknown.
507+
/// Test that external environments (not under conda_dir) created with -n
508+
/// return the name for name-based activation.
477509
#[test]
478-
fn name_based_env_returns_name_when_conda_dir_unknown() {
479-
// Create a temp directory structure simulating a name-based conda env
480-
let temp_dir = std::env::temp_dir().join("pet_test_name_based_env");
510+
fn external_name_based_env_returns_name() {
511+
// Create a temp directory simulating an external name-based conda env
512+
let temp_dir = std::env::temp_dir().join("pet_test_external_name_env");
481513
let conda_meta_dir = temp_dir.join("myenv").join("conda-meta");
482514
std::fs::create_dir_all(&conda_meta_dir).unwrap();
483515

@@ -490,13 +522,14 @@ mod tests {
490522
.unwrap();
491523

492524
let env_path = temp_dir.join("myenv");
525+
// conda_dir is known but env is NOT under it (external environment)
526+
let conda_dir = Some(std::path::PathBuf::from("/some/other/conda"));
493527

494-
// When conda_dir is None but env was created with -n, name should be returned
495-
let name = get_conda_env_name(&env_path, &env_path, &None);
528+
let name = get_conda_env_name(&env_path, &env_path, &conda_dir);
496529
assert_eq!(
497530
name,
498531
Some("myenv".to_string()),
499-
"Name-based env should return the name"
532+
"Name-based external env should return the name"
500533
);
501534

502535
// Cleanup

0 commit comments

Comments
 (0)