remote-helper: remove check for fast-forward
Since the commit is now always pushed to the Radicle storage, there is no need to check for fast-forward. If heads diverge, it will be reported by the quorum error.
This commit is contained in:
parent
119a124897
commit
690f6b02c0
|
|
@ -361,9 +361,9 @@ pub fn run(
|
|||
.ok_or(Error::UnknownObjectType { oid: *src })?;
|
||||
|
||||
let canonical = canonical::Canonical::new(me, object, canonical)?;
|
||||
match canonical.quorum(&working) {
|
||||
match canonical.quorum() {
|
||||
Ok(quorum) => set_canonical_refs.push(quorum),
|
||||
Err(e) => canonical::io::handle_error(e, &dst, hints)?,
|
||||
Err(e) => canonical::io::handle_error(e)?,
|
||||
}
|
||||
}
|
||||
Ok(explorer)
|
||||
|
|
|
|||
|
|
@ -1,24 +1,12 @@
|
|||
use radicle::git;
|
||||
use radicle::git::canonical;
|
||||
use radicle::git::canonical::effects;
|
||||
use radicle::git::raw::Repository;
|
||||
use radicle::git::canonical::error::QuorumError;
|
||||
use radicle::git::canonical::QuorumWithConvergence;
|
||||
use radicle::prelude::Did;
|
||||
|
||||
use super::error;
|
||||
|
||||
pub(crate) struct Vote {
|
||||
object: canonical::Object,
|
||||
}
|
||||
|
||||
impl Vote {
|
||||
pub(crate) fn id(&self) -> git::Oid {
|
||||
self.object.id()
|
||||
}
|
||||
}
|
||||
|
||||
/// Validates a vote to update a canonical reference during push.
|
||||
pub(crate) struct Canonical<'a, 'b, 'r, R> {
|
||||
vote: Vote,
|
||||
canonical: canonical::CanonicalWithConvergence<'a, 'b, 'r, R>,
|
||||
}
|
||||
|
||||
|
|
@ -33,7 +21,6 @@ where
|
|||
) -> Result<Self, canonical::error::FindObjectsError> {
|
||||
let canonical = canonical.find_objects()?;
|
||||
Ok(Self {
|
||||
vote: Vote { object },
|
||||
canonical: canonical.with_convergence(me, object),
|
||||
})
|
||||
}
|
||||
|
|
@ -55,89 +42,47 @@ where
|
|||
/// Ensures that the new head and the canonical commit do not diverge.
|
||||
///
|
||||
/// [`head`]: crate::push::canonical::Canonical::head
|
||||
pub fn quorum(
|
||||
self,
|
||||
working: &Repository,
|
||||
) -> Result<(git::Qualified<'a>, canonical::Object), error::Canonical> {
|
||||
match self.canonical.quorum() {
|
||||
Ok(result) => {
|
||||
let canonical::QuorumWithConvergence { quorum, converges } = result;
|
||||
let canonical::Quorum { refname, object } = quorum;
|
||||
let quorum_head = object.id();
|
||||
// Canonical head is an ancestor of head.
|
||||
let is_ff = self.vote.id() == quorum_head
|
||||
|| working
|
||||
.graph_descendant_of(*self.vote.id(), *quorum_head)
|
||||
.map_err(|err| {
|
||||
error::Canonical::graph_descendant(self.vote.id(), quorum_head, err)
|
||||
})?;
|
||||
|
||||
if !is_ff && !converges {
|
||||
Err(error::Canonical::heads_diverge(self.vote.id(), quorum_head))
|
||||
} else {
|
||||
Ok((refname, object))
|
||||
}
|
||||
}
|
||||
Err(err) => Err(err.into()),
|
||||
}
|
||||
pub fn quorum(self) -> Result<(git::Qualified<'a>, canonical::Object), QuorumError> {
|
||||
self.canonical
|
||||
.quorum()
|
||||
.map(|QuorumWithConvergence { quorum, .. }| (quorum.refname, quorum.object))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod io {
|
||||
use radicle::git;
|
||||
use radicle::git::canonical::error::QuorumError;
|
||||
|
||||
use crate::push::error;
|
||||
use crate::{hint, warn};
|
||||
use crate::warn;
|
||||
|
||||
/// Handle recoverable errors, printing relevant information to the
|
||||
/// terminal. Otherwise, convert the error into an unrecoverable error
|
||||
/// [`error::CanonicalUnrecoverable`].
|
||||
pub fn handle_error(
|
||||
e: error::Canonical,
|
||||
canonical: &git::Qualified,
|
||||
hints: bool,
|
||||
) -> Result<(), error::CanonicalUnrecoverable> {
|
||||
pub fn handle_error(e: QuorumError) -> Result<(), error::CanonicalUnrecoverable> {
|
||||
match e {
|
||||
error::Canonical::GraphDescendant(e) => Err(e.into()),
|
||||
error::Canonical::HeadsDiverge(e) => {
|
||||
if hints {
|
||||
hint(
|
||||
format!("you are attempting to push a commit that would cause \
|
||||
your upstream to diverge from the canonical reference {canonical}"),
|
||||
);
|
||||
hint(
|
||||
"to integrate the remote changes, run `git pull --rebase` \
|
||||
and try again",
|
||||
);
|
||||
}
|
||||
Err(e.into())
|
||||
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(())
|
||||
}
|
||||
error::Canonical::Quorum(e) => {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
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(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,30 +18,6 @@ pub enum CanonicalUnrecoverable {
|
|||
Git { source: git::raw::Error },
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum Canonical {
|
||||
#[error(transparent)]
|
||||
GraphDescendant(GraphDescendant),
|
||||
#[error(transparent)]
|
||||
HeadsDiverge(HeadsDiverge),
|
||||
#[error(transparent)]
|
||||
Quorum(#[from] canonical::error::QuorumError),
|
||||
}
|
||||
|
||||
impl Canonical {
|
||||
pub fn graph_descendant(head: git::Oid, canonical: git::Oid, source: git::raw::Error) -> Self {
|
||||
Self::GraphDescendant(GraphDescendant {
|
||||
head,
|
||||
canonical,
|
||||
source,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn heads_diverge(head: git::Oid, canonical: git::Oid) -> Self {
|
||||
Self::HeadsDiverge(HeadsDiverge { head, canonical })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error("failed to check if {head} is an ancestor of {canonical} due to: {source}")]
|
||||
pub struct GraphDescendant {
|
||||
|
|
|
|||
Loading…
Reference in New Issue