90 lines
3.2 KiB
Rust
90 lines
3.2 KiB
Rust
use radicle::git;
|
|
use radicle::git::canonical;
|
|
use radicle::git::canonical::QuorumWithConvergence;
|
|
use radicle::git::canonical::effects;
|
|
use radicle::git::canonical::error::QuorumError;
|
|
use radicle::prelude::Did;
|
|
|
|
/// Validates a vote to update a canonical reference during push.
|
|
pub(crate) struct Canonical<'a, 'b, 'r, R> {
|
|
canonical: canonical::CanonicalWithConvergence<'a, 'b, 'r, R>,
|
|
}
|
|
|
|
impl<'a, 'b, 'r, R> Canonical<'a, 'b, 'r, R>
|
|
where
|
|
R: effects::Ancestry + effects::FindMergeBase + effects::FindObjects,
|
|
{
|
|
pub(super) fn new(
|
|
me: Did,
|
|
object: canonical::Object,
|
|
canonical: canonical::Canonical<'a, 'b, 'r, R, canonical::Initial>,
|
|
) -> Result<Self, canonical::error::FindObjectsError> {
|
|
let canonical = canonical.find_objects()?;
|
|
Ok(Self {
|
|
canonical: canonical.with_convergence(me, object),
|
|
})
|
|
}
|
|
|
|
/// Calculates the quorum of the [`git::canonical::Canonical`] provided.
|
|
///
|
|
/// In some cases, it ensures that the head commit is attempting to converge
|
|
/// with the set of commits of the other [`Did`]s.
|
|
///
|
|
/// If a quorum is found, then it is also ensured that the new head commit
|
|
/// is a descendant of the current canonical commit; otherwise, the commits
|
|
/// are considered diverging.
|
|
///
|
|
/// # Errors
|
|
///
|
|
/// Ensures that the commits of the other [`Did`]s are in the working
|
|
/// copy, and that checks that any two commits are related in the graph.
|
|
///
|
|
/// Ensures that the new head and the canonical commit do not diverge.
|
|
pub(super) fn quorum(
|
|
self,
|
|
) -> Result<(git::fmt::Qualified<'a>, canonical::Object), QuorumError> {
|
|
self.canonical
|
|
.quorum()
|
|
.map(|QuorumWithConvergence { quorum, .. }| (quorum.refname, quorum.object))
|
|
}
|
|
}
|
|
|
|
pub(crate) mod io {
|
|
use radicle::git::canonical::error::QuorumError;
|
|
|
|
use crate::push::error;
|
|
use crate::warn;
|
|
|
|
/// Handle recoverable errors, printing relevant information to the
|
|
/// terminal. Otherwise, convert the error into an unrecoverable error
|
|
/// [`error::CanonicalUnrecoverable`].
|
|
pub(crate) fn handle_error(e: QuorumError) -> Result<(), error::CanonicalUnrecoverable> {
|
|
match e {
|
|
QuorumError::Convergence(err) => Err(err.into()),
|
|
QuorumError::MergeBase(err) => Err(err.into()),
|
|
e @ QuorumError::DivergingCommits { .. } => {
|
|
warn(e.to_string());
|
|
warn("it is recommended to find a commit to agree upon");
|
|
Ok(())
|
|
}
|
|
e @ QuorumError::DivergingTags { .. } => {
|
|
warn(e.to_string());
|
|
warn("it is recommended to find a tag to agree upon");
|
|
Ok(())
|
|
}
|
|
e @ QuorumError::DifferentTypes { .. } => {
|
|
warn(e.to_string());
|
|
warn(
|
|
"it is recommended to find an object type (either commit or tag) to agree upon",
|
|
);
|
|
Ok(())
|
|
}
|
|
e @ QuorumError::NoCandidates { .. } => {
|
|
warn(e.to_string());
|
|
warn("it is recommended to find an object (either commit or tag) to agree upon");
|
|
Ok(())
|
|
}
|
|
}
|
|
}
|
|
}
|