From eeec2008e88cd047f6188e9b4459f548e1cd01ce Mon Sep 17 00:00:00 2001 From: Alexis Sellier Date: Tue, 11 Apr 2023 14:11:23 +0200 Subject: [PATCH] node: Allow most refs to be force-updated Previously, during the "transfer" stage of a fetch, we used `force: false`, which didn't allow refs to be force-updated. This change makes it possible to fetch force-updated refs, but ensures that the sigrefs branch is never force-updated. --- radicle-node/src/worker/fetch.rs | 49 +++++++++++++++++++---- radicle-node/src/worker/fetch/refspecs.rs | 6 +-- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/radicle-node/src/worker/fetch.rs b/radicle-node/src/worker/fetch.rs index eeb20c4a..888e8aef 100644 --- a/radicle-node/src/worker/fetch.rs +++ b/radicle-node/src/worker/fetch.rs @@ -234,24 +234,59 @@ impl<'a> StagingPhaseFinal<'a> { { let specs = verifications .into_iter() - .filter_map(|(remote, verified)| match verified { + .flat_map(|(remote, verified)| match verified { VerifiedRemote::Failed { reason } => { log::warn!( target: "worker", "{remote} failed to verify, will not fetch any further refs: {reason}", ); - None + vec![] } VerifiedRemote::Success { remote, .. } => { - let ns = remote.id.to_namespace().with_pattern(git::refspec::STAR); - Some( + let ns = remote.id.to_namespace(); + let mut refspecs = vec![]; + + // First add the standard git refs. + let heads = ns.join(git::refname!("refs/heads")); + let cobs = ns.join(git::refname!("refs/cobs")); + let tags = ns.join(git::refname!("refs/tags")); + let notes = ns.join(git::refname!("refs/notes")); + + for refname in [heads, cobs, tags, notes] { + let pattern = refname.with_pattern(git::refspec::STAR); + refspecs.push( + Refspec { + src: pattern.clone(), + dst: pattern, + force: true, + } + .to_string(), + ); + } + + // Then add the special refs. + let id = ns.join(&*radicle::git::refs::storage::IDENTITY_BRANCH); + let sigrefs = ns.join(&*radicle::git::refs::storage::SIGREFS_BRANCH); + + refspecs.push( Refspec { - src: ns.clone(), - dst: ns, + src: id.clone(), + dst: id, + // Nb. The identity branch is allowed to be force-updated. + force: true, + } + .to_string(), + ); + refspecs.push( + Refspec { + src: sigrefs.clone(), + dst: sigrefs, + // Nb. Sigrefs are never force-updated. force: false, } .to_string(), - ) + ); + refspecs } }) .collect::>(); diff --git a/radicle-node/src/worker/fetch/refspecs.rs b/radicle-node/src/worker/fetch/refspecs.rs index 57518781..7ef1b05f 100644 --- a/radicle-node/src/worker/fetch/refspecs.rs +++ b/radicle-node/src/worker/fetch/refspecs.rs @@ -21,14 +21,14 @@ pub struct Refspec { impl fmt::Display for Refspec where - T: AsRef, - U: AsRef, + T: fmt::Display, + U: fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.force { f.write_char('+')?; } - write!(f, "{}:{}", self.src.as_ref(), self.dst.as_ref()) + write!(f, "{}:{}", self.src, self.dst) } }