diff --git a/librad/src/git/identities/person.rs b/librad/src/git/identities/person.rs index eec11b89e..bd697c75f 100644 --- a/librad/src/git/identities/person.rs +++ b/librad/src/git/identities/person.rs @@ -5,7 +5,7 @@ use std::{convert::TryFrom, fmt::Debug}; -use radicle_git_ext::{is_not_found_err, OneLevel}; +use radicle_git_ext::{self as ext, is_not_found_err, OneLevel}; use super::{ super::{ @@ -189,6 +189,21 @@ where Ok(verified(storage).newer(a, b)?) } +pub fn fast_forward(storage: &Storage, latest: &VerifiedPerson) -> Result, Error> { + let urn = latest.urn().with_path(None); + let id_ref = super::common::IdRef::from(&urn); + let canonical = id_ref.oid(storage)?; + let tip = latest.content_id; + Ok(if storage.as_raw().graph_descendant_of(*tip, *canonical)? { + id_ref + .update(storage, tip, &format!("fast-forward to {}", tip)) + .map_err(|e| Error::Store(e.into()))?; + Some(tip) + } else { + None + }) +} + fn identities(storage: &S) -> Identities where S: AsRef, diff --git a/librad/src/git/replication.rs b/librad/src/git/replication.rs index ca426329c..8ce0e3882 100644 --- a/librad/src/git/replication.rs +++ b/librad/src/git/replication.rs @@ -805,9 +805,15 @@ mod project { project_urn: &Urn, ) -> Result<(), Error> { let delegate_urn = person.urn(); - ensure_rad_id(storage, &delegate_urn, person.content_id)?; - tracking::track(storage, &delegate_urn, peer)?; - tracking::track(storage, project_urn, peer)?; + + // if the identity is known we see if we can fast-forward it + if storage.has_urn(&delegate_urn)? { + identities::person::fast_forward(storage, person)?; + } else { + ensure_rad_id(storage, &delegate_urn, person.content_id)?; + tracking::track(storage, &delegate_urn, peer)?; + tracking::track(storage, project_urn, peer)?; + } // Now point our view to the top-level symref( @@ -927,7 +933,7 @@ mod project { S: AsRef, { let storage = storage.as_ref(); - identities::project::verify_with(storage, &urn, |delegate| { + identities::project::verify_with(storage, urn, |delegate| { let refname = Reference::rad_delegate(Namespace::from(urn.clone()), &delegate).with_remote(peer); storage.reference_oid(&refname).map(|oid| oid.into()) diff --git a/test/src/test/integration/librad/scenario/updated_delegate.rs b/test/src/test/integration/librad/scenario/updated_delegate.rs index a14a53538..18a490766 100644 --- a/test/src/test/integration/librad/scenario/updated_delegate.rs +++ b/test/src/test/integration/librad/scenario/updated_delegate.rs @@ -1,4 +1,4 @@ -// Copyright © 2019-2020 The Radicle Foundation +// Copyright © 2021 The Radicle Link Contributors // // This file is part of radicle-link, distributed under the GPLv3 with Radicle // Linking Exception. For full terms see the included LICENSE file.