Skip to content

Commit 3f98bfc

Browse files
committed
fix: tighten Poetry cache path matching (Fixes #398)
1 parent 172d4b1 commit 3f98bfc

File tree

1 file changed

+110
-4
lines changed

1 file changed

+110
-4
lines changed

crates/pet-poetry/src/lib.rs

Lines changed: 110 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,7 @@ fn is_poetry_cache_environment(path: &Path) -> bool {
4545
// - Linux: ~/.cache/pypoetry/virtualenvs/
4646
// - macOS: ~/Library/Caches/pypoetry/virtualenvs/
4747
// - Windows: %LOCALAPPDATA%\pypoetry\Cache\virtualenvs\
48-
let path_str = path.to_str().unwrap_or_default();
49-
50-
// Check if path contains typical Poetry cache directory structure
51-
if path_str.contains("pypoetry") && path_str.contains("virtualenvs") {
48+
if has_poetry_cache_components(path) {
5249
// Further validate by checking if the directory name matches Poetry's naming pattern
5350
// Pattern: {name}-{8-char-hash}-py or just .venv
5451
if let Some(dir_name) = path.file_name().and_then(|n| n.to_str()) {
@@ -63,6 +60,21 @@ fn is_poetry_cache_environment(path: &Path) -> bool {
6360
false
6461
}
6562

63+
fn has_poetry_cache_components(path: &Path) -> bool {
64+
let mut found_pypoetry = false;
65+
66+
path.components()
67+
.filter_map(|component| component.as_os_str().to_str())
68+
.any(|component| {
69+
if component.eq_ignore_ascii_case("pypoetry") {
70+
found_pypoetry = true;
71+
return false;
72+
}
73+
74+
found_pypoetry && component.eq_ignore_ascii_case("virtualenvs")
75+
})
76+
}
77+
6678
/// Check if a .venv directory is an in-project Poetry environment
6779
/// This is for the case when virtualenvs.in-project = true is set.
6880
/// We check if the parent directory has Poetry configuration files.
@@ -359,6 +371,100 @@ mod tests {
359371
use super::*;
360372
use pet_core::os_environment::EnvironmentApi;
361373

374+
fn path_from_components(components: &[&str]) -> PathBuf {
375+
let mut path = PathBuf::new();
376+
for component in components {
377+
path.push(component);
378+
}
379+
path
380+
}
381+
382+
#[test]
383+
fn test_poetry_cache_environment_requires_exact_cache_components() {
384+
let path = path_from_components(&[
385+
"home",
386+
"user",
387+
".cache",
388+
"pypoetry",
389+
"virtualenvs",
390+
"project-1a2b3c4d-py3.11",
391+
]);
392+
393+
assert!(is_poetry_cache_environment(&path));
394+
}
395+
396+
#[test]
397+
fn test_poetry_cache_environment_allows_windows_cache_component() {
398+
let path = path_from_components(&[
399+
"Users",
400+
"user",
401+
"AppData",
402+
"Local",
403+
"pypoetry",
404+
"Cache",
405+
"virtualenvs",
406+
"project-1a2b3c4d-py3.11",
407+
]);
408+
409+
assert!(is_poetry_cache_environment(&path));
410+
}
411+
412+
#[test]
413+
fn test_poetry_cache_environment_rejects_substring_cache_components() {
414+
let path = path_from_components(&[
415+
"Users",
416+
"pypoetry_user",
417+
"virtualenvs_backup",
418+
"project-1a2b3c4d-py3.11",
419+
]);
420+
421+
assert!(!is_poetry_cache_environment(&path));
422+
}
423+
424+
#[test]
425+
fn test_poetry_cache_environment_requires_ordered_cache_components() {
426+
let path = path_from_components(&[
427+
"home",
428+
"user",
429+
".cache",
430+
"virtualenvs",
431+
"pypoetry",
432+
"project-1a2b3c4d-py3.11",
433+
]);
434+
435+
assert!(!is_poetry_cache_environment(&path));
436+
}
437+
438+
#[test]
439+
fn test_poetry_cache_environment_allows_mixed_case_cache_components() {
440+
let path = path_from_components(&[
441+
"Users",
442+
"user",
443+
"AppData",
444+
"Local",
445+
"PyPoetry",
446+
"Cache",
447+
"VirtualEnvs",
448+
"project-1a2b3c4d-py3.11",
449+
]);
450+
451+
assert!(is_poetry_cache_environment(&path));
452+
}
453+
454+
#[test]
455+
fn test_poetry_cache_environment_requires_poetry_env_name() {
456+
let path = path_from_components(&[
457+
"home",
458+
"user",
459+
".cache",
460+
"pypoetry",
461+
"virtualenvs",
462+
"not-a-poetry-env",
463+
]);
464+
465+
assert!(!is_poetry_cache_environment(&path));
466+
}
467+
362468
#[test]
363469
fn test_sync_search_result_from_replaces_cached_result() {
364470
let environment = EnvironmentApi::new();

0 commit comments

Comments
 (0)