systemprompt_models/paths/
build.rs1use std::path::{Path, PathBuf};
2
3use super::PathError;
4use crate::profile::PathsConfig;
5
6#[derive(Debug, Clone)]
7pub struct BuildPaths {
8 bin: PathBuf,
9}
10
11impl BuildPaths {
12 pub fn from_profile(paths: &PathsConfig) -> Self {
13 Self {
14 bin: PathBuf::from(&paths.bin),
15 }
16 }
17
18 pub fn resolve_binary(&self, name: &str) -> Result<PathBuf, PathError> {
19 let mut searched = Vec::new();
20
21 let exe_name = format!("{}{}", name, std::env::consts::EXE_SUFFIX);
22 let primary = self.bin.join(&exe_name);
23 searched.push(primary.clone());
24
25 let sibling = self.sibling_bin_path();
26 let alt = sibling.as_ref().map(|s| s.join(&exe_name));
27 if let Some(ref alt_path) = alt {
28 searched.push(alt_path.clone());
29 }
30
31 let alt_exists = alt.as_ref().filter(|p| p.exists());
32
33 match (primary.exists(), alt_exists) {
34 (true, Some(alt_path)) => {
35 let primary_mtime = std::fs::metadata(&primary).and_then(|m| m.modified()).ok();
36 let alt_mtime = std::fs::metadata(alt_path).and_then(|m| m.modified()).ok();
37 match (primary_mtime, alt_mtime) {
38 (Some(p), Some(a)) if a > p => Self::ensure_absolute(alt_path.clone()),
39 _ => Self::ensure_absolute(primary),
40 }
41 },
42 (true, None) => Self::ensure_absolute(primary),
43 (false, Some(alt_path)) => Self::ensure_absolute(alt_path.clone()),
44 (false, None) => {
45 if !std::env::consts::EXE_SUFFIX.is_empty() {
46 let path = self.bin.join(name);
47 searched.push(path.clone());
48 if path.exists() {
49 return Self::ensure_absolute(path);
50 }
51 }
52 Err(PathError::BinaryNotFound {
53 name: name.to_owned(),
54 searched,
55 })
56 },
57 }
58 }
59
60 pub fn resolve_self() -> Result<PathBuf, PathError> {
67 let exe = std::env::current_exe()
68 .map_err(|source| PathError::CurrentExeUnavailable { source })?;
69 Self::ensure_absolute(exe)
70 }
71
72 fn sibling_bin_path(&self) -> Option<PathBuf> {
73 let dir_name = self.bin.file_name()?.to_str()?;
74 let sibling_name = match dir_name {
75 "release" => "debug",
76 "debug" => "release",
77 _ => return None,
78 };
79 Some(self.bin.with_file_name(sibling_name))
80 }
81
82 fn ensure_absolute(path: PathBuf) -> Result<PathBuf, PathError> {
83 if path.is_absolute() {
84 Ok(path)
85 } else {
86 std::fs::canonicalize(&path).map_err(|source| PathError::CanonicalizeFailed {
87 path,
88 field: "binary",
89 source,
90 })
91 }
92 }
93
94 pub fn binary_exists(&self, name: &str) -> bool {
95 self.resolve_binary(name).is_ok()
96 }
97
98 pub fn bin(&self) -> &Path {
99 &self.bin
100 }
101}