Skip to content

Commit 7f73e80

Browse files
committed
fix: enhance conda environment name retrieval logic for path-based and name-based environments
1 parent f0637ef commit 7f73e80

File tree

1 file changed

+82
-31
lines changed

1 file changed

+82
-31
lines changed

crates/pet-conda/src/environments.rs

Lines changed: 82 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -214,25 +214,62 @@ fn get_conda_env_name(
214214
* And example is `# cmd: <conda install directory>\Scripts\conda-script.py create -n sample``
215215
* And example is `# cmd: conda create -n sample``
216216
*
217-
* This function returns the name of the conda environment.
217+
* This function returns the name of the conda environment based on how it was created:
218+
* - If created with --prefix/-p (path-based): returns None (activation must use full path)
219+
* - If created with --name/-n (name-based): returns the folder name (can use named activation)
220+
* - If we can't determine: returns the folder name (preserve existing behavior)
218221
*/
219222
fn get_conda_env_name_from_history_file(env_path: &Path, prefix: &Path) -> Option<String> {
220223
let name = prefix
221224
.file_name()
222225
.map(|name| name.to_str().unwrap_or_default().to_string());
223226

224-
if let Some(name) = name {
227+
if let Some(ref name) = name {
225228
if let Some(line) = get_conda_creation_line_from_history(env_path) {
226229
// Sample lines
227230
// # cmd: <conda install directory>\Scripts\conda-script.py create -n samlpe1
228231
// # cmd: <conda install directory>\Scripts\conda-script.py create -p <full path>
229232
// # cmd: /Users/donjayamanne/miniconda3/bin/conda create -n conda1
230-
if is_conda_env_name_in_cmd(line, &name) {
231-
return Some(name);
233+
// # cmd: /usr/bin/conda create --prefix ./prefix-envs/.conda1 python=3.12 -y
234+
235+
// Check if environment was created with --prefix/-p (path-based)
236+
// In this case, return None so activation uses full path
237+
if is_path_based_conda_env(&line) {
238+
return None;
239+
}
240+
241+
// Check if environment was created with --name/-n (name-based)
242+
// In this case, return the folder name for named activation
243+
if is_name_based_conda_env(&line) {
244+
return Some(name.clone());
232245
}
233246
}
234247
}
235-
None
248+
// If we can't determine from history, return folder name (preserve existing behavior)
249+
name
250+
}
251+
252+
/// Check if the conda create command used --prefix or -p (path-based environment)
253+
fn is_path_based_conda_env(cmd_line: &str) -> bool {
254+
// Look for " -p " or " --prefix " after "create"
255+
// We need to be careful to match the flag, not just any occurrence of -p
256+
let lower = cmd_line.to_lowercase();
257+
if let Some(create_idx) = lower.find(" create ") {
258+
let after_create = &lower[create_idx..];
259+
return after_create.contains(" -p ") || after_create.contains(" --prefix ");
260+
}
261+
false
262+
}
263+
264+
/// Check if the conda create command used --name or -n (name-based environment)
265+
fn is_name_based_conda_env(cmd_line: &str) -> bool {
266+
// Look for " -n " or " --name " after "create"
267+
let lower = cmd_line.to_lowercase();
268+
if let Some(create_idx) = lower.find(" create ") {
269+
let after_create = &lower[create_idx..];
270+
return after_create.contains(" -n ") || after_create.contains(" --name ");
271+
}
272+
false
236273
}
237274

238275
fn get_conda_dir_from_cmd(cmd_line: String) -> Option<PathBuf> {
@@ -297,17 +334,6 @@ fn get_conda_dir_from_cmd(cmd_line: String) -> Option<PathBuf> {
297334
None
298335
}
299336

300-
fn is_conda_env_name_in_cmd(cmd_line: String, name: &str) -> bool {
301-
// Sample lines
302-
// # cmd: <conda install directory>\Scripts\conda-script.py create -n samlpe1
303-
// # cmd: <conda install directory>\Scripts\conda-script.py create -p <full path>
304-
// # cmd: /Users/donjayamanne/miniconda3/bin/conda create -n conda1
305-
// # cmd_line: "# cmd: /usr/bin/conda create -p ./prefix-envs/.conda1 python=3.12 -y"
306-
// Look for "-n <name>" in the command line
307-
cmd_line.contains(format!("-n {name}").as_str())
308-
|| cmd_line.contains(format!("--name {name}").as_str())
309-
}
310-
311337
pub fn get_activation_command(
312338
env: &CondaEnvironment,
313339
manager: &EnvManager,
@@ -371,22 +397,47 @@ mod tests {
371397
}
372398

373399
#[test]
374-
#[cfg(unix)]
375-
fn verify_conda_env_name() {
376-
let line = "# cmd: /Users/donjayamanne/.pyenv/versions/mambaforge-22.11.1-3/lib/python3.10/site-packages/conda/__main__.py create --yes --name .conda python=3.12";
377-
assert!(is_conda_env_name_in_cmd(line.to_string(), ".conda"));
378-
379-
let mut line = "# cmd: /Users/donjayamanne/.pyenv/versions/mambaforge-22.11.1-3/lib/python3.10/site-packages/conda/__main__.py create --yes -n .conda python=3.12";
380-
assert!(is_conda_env_name_in_cmd(line.to_string(), ".conda"));
381-
382-
line = "# cmd: /Users/donjayamanne/.pyenv/versions/mambaforge-22.11.1-3/lib/python3.10/site-packages/conda/__main__.py create --yes --name .conda python=3.12";
383-
assert!(!is_conda_env_name_in_cmd(line.to_string(), "base"));
384-
385-
line = "# cmd: /Users/donjayamanne/.pyenv/versions/mambaforge-22.11.1-3/lib/python3.10/site-packages/conda/__main__.py create --yes -p .conda python=3.12";
386-
assert!(!is_conda_env_name_in_cmd(line.to_string(), "base"));
400+
fn test_is_path_based_conda_env() {
401+
// Path-based environments use --prefix or -p
402+
assert!(is_path_based_conda_env(
403+
"# cmd: /usr/bin/conda create --yes --prefix .conda python=3.12"
404+
));
405+
assert!(is_path_based_conda_env(
406+
"# cmd: /usr/bin/conda create -p .conda python=3.12"
407+
));
408+
assert!(is_path_based_conda_env(
409+
"# cmd: C:\\Users\\user\\miniconda3\\Scripts\\conda.exe create --prefix .conda python=3.9"
410+
));
411+
412+
// Name-based environments use --name or -n
413+
assert!(!is_path_based_conda_env(
414+
"# cmd: /usr/bin/conda create -n myenv python=3.12"
415+
));
416+
assert!(!is_path_based_conda_env(
417+
"# cmd: /usr/bin/conda create --name myenv python=3.12"
418+
));
419+
}
387420

388-
line = "# cmd: /Users/donjayamanne/.pyenv/versions/mambaforge-22.11.1-3/lib/python3.10/site-packages/conda/__main__.py create --yes -p .conda python=3.12";
389-
assert!(!is_conda_env_name_in_cmd(line.to_string(), ".conda"));
421+
#[test]
422+
fn test_is_name_based_conda_env() {
423+
// Name-based environments use --name or -n
424+
assert!(is_name_based_conda_env(
425+
"# cmd: /usr/bin/conda create -n myenv python=3.12"
426+
));
427+
assert!(is_name_based_conda_env(
428+
"# cmd: /usr/bin/conda create --name myenv python=3.12"
429+
));
430+
assert!(is_name_based_conda_env(
431+
"# cmd: C:\\Users\\user\\miniconda3\\Scripts\\conda.exe create -n myenv python=3.9"
432+
));
433+
434+
// Path-based environments use --prefix or -p
435+
assert!(!is_name_based_conda_env(
436+
"# cmd: /usr/bin/conda create --prefix .conda python=3.12"
437+
));
438+
assert!(!is_name_based_conda_env(
439+
"# cmd: /usr/bin/conda create -p .conda python=3.12"
440+
));
390441
}
391442

392443
/// Test that path-based conda environments (created with --prefix) return None for name

0 commit comments

Comments
 (0)