mod io;
use std::path::Path;
use crate::git_helpers::git_oid_to_git2_oid;
use crate::workspace::Workspace;
pub fn git_diff() -> std::io::Result<String> {
let repo = io::discover_repo(Path::new("."))?;
diff_against_head(&repo)
}
pub fn git_diff_in_repo(repo_root: &Path) -> std::io::Result<String> {
let repo = io::discover_repo(repo_root)?;
diff_against_head(&repo)
}
fn diff_against_head(repo: &git2::Repository) -> std::io::Result<String> {
match io::resolve_head_tree_oid(repo)? {
io::HeadTreeOid::Tree(tree_oid) => io::diff_from_tree_oid_impl(repo, tree_oid),
io::HeadTreeOid::UnbornBranch => io::diff_from_empty_tree_impl(repo),
}
}
pub fn git_diff_from(start_oid: &str) -> std::io::Result<String> {
let repo = io::discover_repo(Path::new("."))?;
let oid = git2::Oid::from_str(start_oid).map_err(|_| {
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("Invalid commit OID: {start_oid}"),
)
})?;
io::diff_from_oid_impl(&repo, oid)
}
pub fn get_git_diff_from_start() -> std::io::Result<String> {
use crate::git_helpers::start_commit::{load_start_point, save_start_commit, StartPoint};
save_start_commit()?;
let repo = io::discover_repo(Path::new("."))?;
match load_start_point()? {
StartPoint::Commit(oid) => {
let git2_oid = git_oid_to_git2_oid(&oid)?;
io::diff_from_oid_impl(&repo, git2_oid)
}
StartPoint::EmptyRepo => io::diff_from_empty_tree_impl(&repo),
}
}
pub fn get_git_diff_from_start_with_workspace(
workspace: &dyn Workspace,
) -> std::io::Result<String> {
use crate::git_helpers::start_commit::{
load_start_point_with_workspace, save_start_commit_with_workspace, StartPoint,
};
if !workspace.exists(std::path::Path::new(".git")) {
return Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
"Workspace has no on-disk git repository",
));
}
let repo = io::discover_repo(Path::new("."))?;
save_start_commit_with_workspace(workspace, &repo)?;
match load_start_point_with_workspace(workspace, &repo)? {
StartPoint::Commit(oid) => {
let git2_oid = git_oid_to_git2_oid(&oid).map_err(|err| {
std::io::Error::new(std::io::ErrorKind::InvalidData, err.to_string())
})?;
io::diff_from_oid_impl(&repo, git2_oid)
}
StartPoint::EmptyRepo => io::diff_from_empty_tree_impl(&repo),
}
}
pub fn get_git_diff_for_review_with_workspace(
workspace: &dyn Workspace,
) -> std::io::Result<(String, String)> {
use crate::git_helpers::review_baseline::{
load_review_baseline_with_workspace, ReviewBaseline,
};
use crate::git_helpers::start_commit::{
load_start_point_with_workspace, save_start_commit_with_workspace, StartPoint,
};
let repo = io::discover_repo(Path::new("."))?;
let baseline = load_review_baseline_with_workspace(workspace).unwrap_or(ReviewBaseline::NotSet);
match baseline {
ReviewBaseline::Commit(oid) => {
let diff = io::diff_from_oid_impl(&repo, oid)?;
Ok((diff, oid.to_string()))
}
ReviewBaseline::NotSet => {
save_start_commit_with_workspace(workspace, &repo)?;
match load_start_point_with_workspace(workspace, &repo)? {
StartPoint::Commit(oid) => {
let git2_oid = git_oid_to_git2_oid(&oid)?;
let diff = io::diff_from_oid_impl(&repo, git2_oid)?;
Ok((diff, oid.to_string()))
}
StartPoint::EmptyRepo => Ok((io::diff_from_empty_tree_impl(&repo)?, String::new())),
}
}
}
}