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.
This commit is contained in:
Alexis Sellier 2023-04-11 14:11:23 +02:00
parent 89b9eb53b7
commit eeec2008e8
No known key found for this signature in database
2 changed files with 45 additions and 10 deletions

View File

@ -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::<Vec<_>>();

View File

@ -21,14 +21,14 @@ pub struct Refspec<T, U> {
impl<T, U> fmt::Display for Refspec<T, U>
where
T: AsRef<git::PatternStr>,
U: AsRef<git::PatternStr>,
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)
}
}