From 4ecd47c08a3dc7e5e8a7cbbaa9bce397de723d52 Mon Sep 17 00:00:00 2001 From: Fintan Halpenny Date: Thu, 24 Jun 2021 13:52:32 +0100 Subject: [PATCH] identities: update on fast-forward When we have a latest head that is a fast-forward of a known delegate then we can update the top-level rad/id to that head, given that both identities also verify. Signed-off-by: Fintan Halpenny --- librad/src/identities/git.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/librad/src/identities/git.rs b/librad/src/identities/git.rs index 63aa28286..afda63b9a 100644 --- a/librad/src/identities/git.rs +++ b/librad/src/identities/git.rs @@ -775,11 +775,29 @@ impl<'a> Identities<'a, Project> { known: Person, latest_head: git2::Oid, ) -> Result { + let is_fast_forward = |known: &Person, head: git2::Oid| { + let commit = self.repo.find_commit(head)?; + self.is_in_ancestry_path(known.content_id.into(), commit.tree_id()) + }; // Nb. technically we could coerce `known` into a `VerifiedPerson` if its // `content_id` equals `latest_head`. Let's not introduce an unsafe // coercion, but rely on caching to be implemented efficiently. if self.is_in_ancestry_path(latest_head, known.revision.into())? { self.as_person().verify(latest_head) + // If the latest is a fast-forward then we can update the top-level + } else if is_fast_forward(&known, latest_head)? { + let latest = self.as_person().verify(latest_head)?; + let _known = self.as_person().verify(known.content_id.into())?; + let urn = reflike!("refs/namespaces") + .join(ext::RefLike::from(known.urn())) + .join((*urn::DEFAULT_PATH).clone()) + .to_string(); + let mut reference = self.repo.find_reference(&urn)?; + reference.set_target( + latest_head, + &format!("fast-forward of identity to {}", latest_head), + )?; + Ok(latest) } else { Err(error::VerifyPerson::NotInAncestryPath { revision: known.revision,