use miette::{IntoDiagnostic, miette};
use std::path::{Path, PathBuf};
use std::sync::RwLock;
static CWD: RwLock<Option<PathBuf>> = RwLock::new(None);
pub fn cwd() -> miette::Result<PathBuf> {
if let Some(p) = CWD.read().expect("cwd lock poisoned").as_ref() {
return Ok(p.clone());
}
let mut cwd = CWD.write().expect("cwd lock poisoned");
if let Some(p) = cwd.as_ref() {
return Ok(p.clone());
}
let p = std::env::current_dir().into_diagnostic()?;
Ok(cwd.insert(p).clone())
}
pub fn find_project_root(start: &Path) -> Option<PathBuf> {
for dir in start.ancestors() {
if dir.join("package.json").is_file() {
return Some(dir.to_path_buf());
}
}
None
}
pub fn find_workspace_root(start: &Path) -> Option<PathBuf> {
start.ancestors().find_map(|dir| {
if dir.join("aube-workspace.yaml").exists() || dir.join("pnpm-workspace.yaml").exists() {
Some(dir.to_path_buf())
} else {
None
}
})
}
pub fn project_root() -> miette::Result<PathBuf> {
let initial_cwd = cwd()?;
find_project_root(&initial_cwd).ok_or_else(|| {
miette!(
"no package.json found in {} or any parent directory",
initial_cwd.display()
)
})
}
pub fn project_root_or_cwd() -> miette::Result<PathBuf> {
let initial_cwd = cwd()?;
Ok(find_project_root(&initial_cwd).unwrap_or(initial_cwd))
}
pub fn set_cwd(path: &Path) -> miette::Result<()> {
let path = if path.is_absolute() {
path.to_path_buf()
} else {
std::env::current_dir().into_diagnostic()?.join(path)
};
*CWD.write().expect("cwd lock poisoned") = Some(path);
Ok(())
}