Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
remote-helper: remove check for fast-forward
Fintan Halpenny committed 8 months ago
commit 690f6b02c0e0d9201807e5711b0e6c6f5a0b5c5a
parent 119a1248979564f85a4cf42c3a9e7ad918557d8b
3 files changed +32 -111
modified crates/radicle-remote-helper/src/push.rs
@@ -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)
modified crates/radicle-remote-helper/src/push/canonical.rs
@@ -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(())
+
            }
+
            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(())
            }
-
            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::NoCandidates { .. } => {
+
                warn(e.to_string());
+
                warn("it is recommended to find an object (either commit or tag) to agree upon");
+
                Ok(())
            }
        }
    }
modified crates/radicle-remote-helper/src/push/error.rs
@@ -19,30 +19,6 @@ pub enum CanonicalUnrecoverable {
}

#[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 {
    head: git::Oid,