diff --git a/crates/radicle-remote-helper/src/push.rs b/crates/radicle-remote-helper/src/push.rs index 41d1785c..eaeccb88 100644 --- a/crates/radicle-remote-helper/src/push.rs +++ b/crates/radicle-remote-helper/src/push.rs @@ -280,6 +280,7 @@ pub fn run( stored, &project, identity.delegates().as_ref(), + identity.threshold(), )?; let converges = canonical::converges( canonical @@ -292,7 +293,7 @@ pub fn run( canonical.modify_vote(me, head.into()); } - match canonical.quorum(identity.threshold(), &working) { + match canonical.quorum(&working) { Ok(canonical_oid) => { // Canonical head is an ancestor of head. let is_ff = head == *canonical_oid diff --git a/crates/radicle/src/git/canonical.rs b/crates/radicle/src/git/canonical.rs index 2f0db2fb..706eec21 100644 --- a/crates/radicle/src/git/canonical.rs +++ b/crates/radicle/src/git/canonical.rs @@ -21,8 +21,10 @@ use super::{lit, Oid, Qualified}; /// /// `Canonical` can then be used for performing calculations about the /// canonicity of the reference, most importantly the [`Canonical::quorum`]. +#[derive(Debug)] pub struct Canonical { tips: BTreeMap, + threshold: usize, } /// Error that can occur when calculation the [`Canonical::quorum`]. @@ -90,6 +92,7 @@ impl Canonical { repo: &S, project: &Project, delegates: &NonEmpty, + threshold: usize, ) -> Result where S: ReadRepository, @@ -98,6 +101,7 @@ impl Canonical { repo, delegates, &lit::refs_heads(project.default_branch()).into(), + threshold, ) } @@ -107,6 +111,7 @@ impl Canonical { repo: &S, delegates: &NonEmpty, name: &Qualified, + threshold: usize, ) -> Result where S: ReadRepository, @@ -127,7 +132,7 @@ impl Canonical { Err(e) => return Err(e), } } - Ok(Canonical { tips }) + Ok(Canonical { tips, threshold }) } /// Return the set of [`Did`]s and their [`Oid`] tip. @@ -171,7 +176,7 @@ impl Canonical { /// /// Also returns an error if `heads` is empty or `threshold` cannot be /// satisified with the number of heads given. - pub fn quorum(&self, threshold: usize, repo: &raw::Repository) -> Result { + pub fn quorum(&self, repo: &raw::Repository) -> Result { let mut candidates = BTreeMap::<_, usize>::new(); // Build a list of candidate commits and count how many "votes" each of them has. @@ -196,11 +201,14 @@ impl Canonical { } } // Keep commits which pass the threshold. - candidates.retain(|_, votes| *votes >= threshold); + candidates.retain(|_, votes| *votes >= self.threshold); - let (mut longest, _) = candidates - .pop_first() - .ok_or(QuorumError::NoCandidates(NoCandidates { threshold }))?; + let (mut longest, _) = + candidates + .pop_first() + .ok_or(QuorumError::NoCandidates(NoCandidates { + threshold: self.threshold, + }))?; // Now that all scores are calculated, figure out what is the longest branch // that passes the threshold. In case of divergence, return an error. @@ -235,7 +243,7 @@ impl Canonical { // | // return Err(QuorumError::Diverging(Diverging { - threshold, + threshold: self.threshold, base: base.into(), longest, head: *head, @@ -271,7 +279,7 @@ mod tests { (did, (*head).into()) }) .collect(); - Canonical { tips }.quorum(threshold, repo) + Canonical { tips, threshold }.quorum(repo) } #[test] diff --git a/crates/radicle/src/storage/git.rs b/crates/radicle/src/storage/git.rs index d6560792..1a49cd7a 100644 --- a/crates/radicle/src/storage/git.rs +++ b/crates/radicle/src/storage/git.rs @@ -752,8 +752,9 @@ impl ReadRepository for Repository { let project = doc.project()?; let branch_ref = git::refs::branch(project.default_branch()); let raw = self.raw(); - let oid = Canonical::default_branch(self, &project, doc.delegates().into())? - .quorum(doc.threshold(), raw)?; + let oid = + Canonical::default_branch(self, &project, doc.delegates().into(), doc.threshold())? + .quorum(raw)?; Ok((branch_ref, oid)) }