terraphim_hooks/
discovery.rs1use std::path::{Path, PathBuf};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
7pub enum BinaryLocation {
8 Path,
10 LocalRelease(PathBuf),
12 CargoHome(PathBuf),
14}
15
16impl BinaryLocation {
17 pub fn path(&self) -> PathBuf {
19 match self {
20 BinaryLocation::Path => PathBuf::from("terraphim-agent"),
21 BinaryLocation::LocalRelease(p) | BinaryLocation::CargoHome(p) => p.clone(),
22 }
23 }
24}
25
26pub fn discover_binary() -> Option<BinaryLocation> {
35 if which_in_path("terraphim-agent") {
37 return Some(BinaryLocation::Path);
38 }
39
40 let local_release = PathBuf::from("./target/release/terraphim-agent");
42 if local_release.exists() && is_executable(&local_release) {
43 return Some(BinaryLocation::LocalRelease(local_release));
44 }
45
46 if let Some(home) = dirs::home_dir() {
48 let cargo_bin = home.join(".cargo/bin/terraphim-agent");
49 if cargo_bin.exists() && is_executable(&cargo_bin) {
50 return Some(BinaryLocation::CargoHome(cargo_bin));
51 }
52 }
53
54 None
55}
56
57fn which_in_path(binary: &str) -> bool {
58 std::process::Command::new("which")
59 .arg(binary)
60 .output()
61 .map(|o| o.status.success())
62 .unwrap_or(false)
63}
64
65#[cfg(unix)]
66fn is_executable(path: &Path) -> bool {
67 use std::os::unix::fs::PermissionsExt;
68 path.metadata()
69 .map(|m| m.permissions().mode() & 0o111 != 0)
70 .unwrap_or(false)
71}
72
73#[cfg(not(unix))]
74fn is_executable(path: &Path) -> bool {
75 path.exists()
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn test_discover_returns_some_or_none() {
84 let _ = discover_binary();
86 }
87
88 #[test]
89 fn test_binary_location_path() {
90 let loc = BinaryLocation::Path;
91 assert_eq!(loc.path(), PathBuf::from("terraphim-agent"));
92 }
93
94 #[test]
95 fn test_binary_location_local_release() {
96 let path = PathBuf::from("/some/path/terraphim-agent");
97 let loc = BinaryLocation::LocalRelease(path.clone());
98 assert_eq!(loc.path(), path);
99 }
100}