use std::path::{Path, PathBuf};
use crate::graph;
use crate::query;
pub(crate) fn current_dir() -> PathBuf {
std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."))
}
pub(crate) fn require_repo(cwd: &Path) -> Result<PathBuf, String> {
require_repo_for_path(cwd, None)
}
pub(crate) fn require_repo_for_path(cwd: &Path, arg_path: Option<&str>) -> Result<PathBuf, String> {
crate::repo::find_scout_root(cwd)
.or_else(|| crate::repo::find_repo_root(cwd))
.or_else(|| root_from_arg(cwd, arg_path))
.ok_or_else(|| {
"no .scout or .git ancestor; run 'devscout init' from the repo or directory root"
.to_string()
})
}
fn root_from_arg(cwd: &Path, arg_path: Option<&str>) -> Option<PathBuf> {
let arg_path = arg_path?;
if !query::looks_like_file_path(arg_path) {
return None;
}
let abs = crate::repo::resolve_from(cwd, Path::new(arg_path));
if !abs.exists() {
return None;
}
crate::repo::find_scout_root(&abs).or_else(|| crate::repo::find_repo_root(&abs))
}
pub(crate) fn repo_relative_arg(cwd: &Path, root: &Path, arg: &str) -> String {
if !query::looks_like_file_path(arg) {
return arg.to_string();
}
let abs = crate::repo::resolve_from(cwd, Path::new(arg));
if !abs.exists() {
return arg.to_string();
}
match abs.strip_prefix(root) {
Ok(rest) if !rest.as_os_str().is_empty() => crate::repo::rel_path(root, &abs),
_ => arg.to_string(),
}
}
pub(crate) fn apply_global_options(
cwd: &Path,
args: &[String],
) -> Result<(PathBuf, Vec<String>), String> {
let mut cwd = cwd.to_path_buf();
let mut idx = 1;
while args.get(idx).map(String::as_str) == Some("-C") {
let Some(dir) = args.get(idx + 1) else {
return Err("no directory given for '-C' option".to_string());
};
let next = crate::repo::resolve_from(&cwd, Path::new(dir));
if !next.is_dir() {
return Err(format!("cannot change to '{dir}': no such directory"));
}
cwd = next;
idx += 2;
}
if idx == 1 {
return Ok((cwd, args.to_vec()));
}
let mut rest = vec![args[0].clone()];
rest.extend_from_slice(&args[idx..]);
Ok((cwd, rest))
}
pub(crate) fn require_graph(root: &Path) -> Result<graph::Graph, (i32, String)> {
graph::read_graph(root).ok_or_else(|| {
(
1,
"no graph.json for this repo — run `devscout map` on a C# scope first".to_string(),
)
})
}