use std::fs;
use std::path::{Path, PathBuf};
use anyhow::{Context, Result, bail};
pub const MARKER: &str = "[package.metadata.slave]";
pub fn find_root() -> Result<PathBuf> {
let cwd = std::env::current_dir().context("failed to read the current directory")?;
find_root_from(&cwd)
}
pub fn package_name(root: &Path) -> Result<String> {
let manifest = root.join("Cargo.toml");
let contents = fs::read_to_string(&manifest)
.with_context(|| format!("failed to read {}", manifest.display()))?;
contents
.lines()
.skip_while(|line| line.trim() != "[package]")
.find_map(|line| {
let value = line.trim().strip_prefix("name")?.trim().strip_prefix('=')?;
Some(value.trim().trim_matches('"').to_owned())
})
.with_context(|| format!("no package name in {}", manifest.display()))
}
fn find_root_from(start: &Path) -> Result<PathBuf> {
for dir in start.ancestors() {
let manifest = dir.join("Cargo.toml");
if let Ok(contents) = fs::read_to_string(&manifest) {
if contents.lines().any(|line| line.trim() == MARKER) {
return Ok(dir.to_path_buf());
}
}
}
bail!(
"not inside a slave application (no Cargo.toml containing `{MARKER}` was found).\n\
Create one with `slave new <name>` and run this command from its directory."
)
}