Search for a binary in common paths and return full path if found
(binary: &str)
| 3843 | |
| 3844 | /// Search for a binary in common paths and return full path if found |
| 3845 | fn discover_tool_path(binary: &str) -> Option<PathBuf> { |
| 3846 | // First try the current PATH via `which` |
| 3847 | if let Ok(output) = std::process::Command::new("which") |
| 3848 | .arg(binary) |
| 3849 | .output() |
| 3850 | { |
| 3851 | if output.status.success() { |
| 3852 | let path_str = String::from_utf8_lossy(&output.stdout).trim().to_string(); |
| 3853 | if !path_str.is_empty() { |
| 3854 | return Some(PathBuf::from(path_str)); |
| 3855 | } |
| 3856 | } |
| 3857 | } |
| 3858 | |
| 3859 | // Search common paths |
| 3860 | for dir in get_common_tool_paths() { |
| 3861 | let candidate = dir.join(binary); |
| 3862 | if candidate.exists() && candidate.is_file() { |
| 3863 | // Verify it's executable |
| 3864 | #[cfg(unix)] |
| 3865 | { |
| 3866 | use std::os::unix::fs::PermissionsExt; |
| 3867 | if let Ok(metadata) = std::fs::metadata(&candidate) { |
| 3868 | if metadata.permissions().mode() & 0o111 != 0 { |
| 3869 | return Some(candidate); |
| 3870 | } |
| 3871 | } |
| 3872 | } |
| 3873 | #[cfg(not(unix))] |
| 3874 | { |
| 3875 | return Some(candidate); |
| 3876 | } |
| 3877 | } |
| 3878 | } |
| 3879 | |
| 3880 | None |
| 3881 | } |
| 3882 | |
| 3883 | /// Auto-discover all tools and add their directories to PATH |
| 3884 | /// Returns a map of tool binary -> full path for discovered tools |
no test coverage detected