1use open_kioku_errors::{OkError, Result};
2use std::fs;
3use std::path::{Path, PathBuf};
4
5pub fn discover_root(start: impl AsRef<Path>) -> Result<PathBuf> {
6 let mut current = start.as_ref().canonicalize()?;
7 loop {
8 if current.join(".git").exists() || current.join("ok.toml").exists() {
9 return Ok(current);
10 }
11 if !current.pop() {
12 return Ok(start.as_ref().canonicalize()?);
13 }
14 }
15}
16
17pub fn branch(root: impl AsRef<Path>) -> Option<String> {
18 let head = fs::read_to_string(root.as_ref().join(".git/HEAD")).ok()?;
19 if let Some(value) = head.strip_prefix("ref: refs/heads/") {
20 return Some(value.trim().to_string());
21 }
22 None
23}
24
25pub fn commit(root: impl AsRef<Path>) -> Option<String> {
26 let head = fs::read_to_string(root.as_ref().join(".git/HEAD")).ok()?;
27 if !head.starts_with("ref: ") {
28 return Some(head.trim().to_string());
29 }
30 let reference = head.trim().strip_prefix("ref: ")?;
31 fs::read_to_string(root.as_ref().join(".git").join(reference))
32 .ok()
33 .map(|value| value.trim().to_string())
34}
35
36pub fn require_repo(root: impl AsRef<Path>) -> Result<PathBuf> {
37 let root = discover_root(root)?;
38 if !root.exists() {
39 return Err(OkError::Repository(format!(
40 "repository root does not exist: {}",
41 root.display()
42 )));
43 }
44 Ok(root)
45}