use std::path::{Path, PathBuf};
use crate::errors::{GrovError, Result};
use crate::git::executor::{run_git, run_git_ok};
pub fn is_bare_repo(path: &Path) -> bool {
let result = run_git(Some(path), &["rev-parse", "--is-bare-repository"]);
matches!(result, Ok(output) if output.stdout == "true")
}
pub fn find_bare_repo(start: &Path) -> Result<PathBuf> {
let start =
std::fs::canonicalize(start).map_err(|_| GrovError::BareRepoNotFound(start.into()))?;
if is_bare_repo(&start) {
return Ok(start);
}
let repo_git = start.join("repo.git");
if repo_git.is_dir() && is_bare_repo(&repo_git) {
return Ok(repo_git);
}
if let Ok(output) = run_git(
None,
&[
"-C",
&start.to_string_lossy(),
"rev-parse",
"--git-common-dir",
],
) && output.status.success()
&& !output.stdout.is_empty()
{
let common_dir = PathBuf::from(&output.stdout);
let common_dir = if common_dir.is_absolute() {
common_dir
} else {
start.join(&common_dir)
};
if let Ok(canonical) = std::fs::canonicalize(&common_dir)
&& is_bare_repo(&canonical)
{
return Ok(canonical);
}
}
let mut current = start.clone();
loop {
if !current.pop() {
break;
}
let repo_git = current.join("repo.git");
if repo_git.is_dir() && is_bare_repo(&repo_git) {
return Ok(repo_git);
}
if is_bare_repo(¤t) {
return Ok(current);
}
}
Err(GrovError::BareRepoNotFound(start))
}
pub fn default_branch(repo: &Path) -> Result<String> {
let output = run_git_ok(Some(repo), &["symbolic-ref", "refs/remotes/origin/HEAD"])?;
let branch = output
.strip_prefix("refs/remotes/origin/")
.unwrap_or(&output);
Ok(branch.to_string())
}