systemprompt_cli/shared/
project.rs1use std::path::{Path, PathBuf};
2use thiserror::Error;
3
4#[derive(Debug, Error)]
5pub enum ProjectError {
6 #[error("Not a systemprompt.io project: {path}\n\nLooking for .systemprompt directory")]
7 ProjectNotFound { path: PathBuf },
8
9 #[error("Failed to resolve path {path}: {source}")]
10 PathResolution {
11 path: PathBuf,
12 #[source]
13 source: std::io::Error,
14 },
15}
16
17#[derive(Debug, Clone)]
18pub struct ProjectRoot(PathBuf);
19
20impl ProjectRoot {
21 pub fn discover() -> Result<Self, ProjectError> {
22 let current = std::env::current_dir().map_err(|e| ProjectError::PathResolution {
23 path: PathBuf::from("."),
24 source: e,
25 })?;
26
27 if current.join(".systemprompt").is_dir() {
28 return Ok(Self(current));
29 }
30
31 let mut search = current.as_path();
32 while let Some(parent) = search.parent() {
33 if parent.join(".systemprompt").is_dir() {
34 return Ok(Self(parent.to_path_buf()));
35 }
36 search = parent;
37 }
38
39 Err(ProjectError::ProjectNotFound { path: current })
40 }
41
42 #[must_use]
43 pub fn as_path(&self) -> &Path {
44 &self.0
45 }
46}
47
48impl AsRef<Path> for ProjectRoot {
49 fn as_ref(&self) -> &Path {
50 &self.0
51 }
52}