use std::sync::atomic::AtomicBool;
use crate::pathspec::Pathspec;
use crate::{Commit, ObjectId, Objects, ReadCommitError, TreeCompareError, TreeCompareLimits};
#[derive(Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub struct Simplification {
pub shown: bool,
pub follow: Vec<ObjectId>,
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum SimplifyError {
#[error("reading parent {id}")]
Parent {
id: ObjectId,
#[source]
source: ReadCommitError,
},
#[error(transparent)]
Trees(#[from] TreeCompareError),
}
impl Objects {
pub fn simplify_commit(
&self,
commit: &Commit,
parents: &[ObjectId],
paths: &Pathspec,
limits: TreeCompareLimits,
cancel: &AtomicBool,
) -> Result<Simplification, SimplifyError> {
let differs = |old: Option<ObjectId>| -> Result<bool, SimplifyError> {
let changes =
self.compare_trees_matching(old, Some(commit.tree()), paths, limits, cancel)?;
Ok(!changes.is_empty())
};
let mut changed = Vec::with_capacity(parents.len());
for &parent in parents {
let tree = self
.read_commit_with(parent, limits.read)
.map_err(|source| SimplifyError::Parent { id: parent, source })?
.tree();
let different = differs(Some(tree))?;
if !different && parents.len() > 1 {
return Ok(Simplification {
shown: false,
follow: vec![parent],
});
}
changed.push(different);
}
let shown = match parents {
[] => differs(None)?,
[_] => changed[0],
_ => true,
};
Ok(Simplification {
shown,
follow: parents.to_vec(),
})
}
}