use std::path::{Path, PathBuf};
use ready_set_sdk::{Error, Result};
use toml_edit::DocumentMut;
#[derive(Debug, Clone)]
pub struct Workspace {
pub root: PathBuf,
pub manifest_path: PathBuf,
pub has_workspace_table: bool,
pub has_package_table: bool,
}
pub fn resolve(cwd: &Path) -> Result<Option<Workspace>> {
let mut nearest_manifest: Option<PathBuf> = None;
let mut cur: Option<&Path> = Some(cwd);
while let Some(dir) = cur {
let manifest = dir.join("Cargo.toml");
if manifest.is_file() && nearest_manifest.is_none() {
nearest_manifest = Some(manifest);
}
if dir.join(".git").exists() {
break;
}
cur = dir.parent();
}
let Some(manifest_path) = nearest_manifest else {
return Ok(None);
};
let raw = std::fs::read_to_string(&manifest_path)?;
let doc: DocumentMut = raw.parse().map_err(|e: toml_edit::TomlError| {
Error::TomlParse(format!("{}: {e}", manifest_path.display()))
})?;
let has_workspace_table = doc.get("workspace").is_some();
let has_package_table = doc.get("package").is_some();
if !has_workspace_table && !has_package_table {
return Ok(None);
}
let root = manifest_path
.parent()
.ok_or_else(|| Error::Other(format!("{} has no parent", manifest_path.display())))?
.to_path_buf();
Ok(Some(Workspace {
root,
manifest_path,
has_workspace_table,
has_package_table,
}))
}