use std::path::{Path, PathBuf};
use async_trait::async_trait;
use crate::path::AbsolutePath;
#[async_trait]
pub trait Git: Send + Sync + std::fmt::Debug {
fn path(&self) -> &AbsolutePath;
async fn is_dirty(&self) -> anyhow::Result<bool>;
async fn current_branch(&self) -> anyhow::Result<Option<String>>;
async fn tag_exists(&self, tag: &str) -> anyhow::Result<bool>;
async fn remote_origin_url(&self) -> anyhow::Result<Option<String>>;
async fn rev_list_count(&self, range: &str) -> anyhow::Result<usize>;
async fn log_message(&self, rev: &str) -> anyhow::Result<String>;
async fn log_subject(&self, rev: &str) -> anyhow::Result<String>;
async fn log_added_commit(&self, path: &Path) -> anyhow::Result<Option<String>>;
async fn diff_tree_names(&self, commit: &str) -> anyhow::Result<Vec<String>>;
async fn diff_names(&self, extra_args: &[&str]) -> anyhow::Result<Vec<String>>;
async fn head_sha(&self) -> anyhow::Result<String>;
async fn path_exists_at_head(&self, path: &Path) -> anyhow::Result<bool>;
async fn add(&self, files: &[PathBuf]) -> anyhow::Result<()>;
async fn commit(&self, message: &str) -> anyhow::Result<()>;
async fn tag(&self, tag_name: &str, message: &str) -> anyhow::Result<()>;
async fn push(&self) -> anyhow::Result<()>;
async fn checkout(&self, branch: &str) -> anyhow::Result<()>;
async fn checkout_or_reset_branch(&self, branch: &str) -> anyhow::Result<()>;
async fn force_push_branch(&self, branch: &str) -> anyhow::Result<()>;
async fn delete_tag(&self, tag: &str) -> anyhow::Result<()>;
async fn push_tag(&self, tag: &str) -> anyhow::Result<()>;
}
pub(crate) mod github_signed_commit;
pub(crate) mod gitlab_signed_commit;
mod operations;
pub(crate) mod ref_format;
pub use github_signed_commit::GitHubSignedCommit;
pub use gitlab_signed_commit::GitLabSignedCommit;
pub use operations::GitWorkdir;
#[cfg(test)]
mod tests;
pub async fn find_workdir(
start: &AbsolutePath,
fs: &dyn crate::filesystem::Filesystem,
) -> Option<AbsolutePath> {
let mut dir = start.to_path_buf();
loop {
if let Ok(git_path) = AbsolutePath::new(dir.join(".git"))
&& fs.exists(&git_path).await.unwrap_or(false)
{
return AbsolutePath::new(&dir).ok();
}
if !dir.pop() {
return None;
}
}
}