Skip to content

Commit

Permalink
replication: adopt rad/self
Browse files Browse the repository at this point in the history
Before this patch a `rad/self` would be replicated, however, there would
be no corresponding `rad/id` at the top-level. This patch introduces the
adding of the `rad/id` and creating a symbolic ref between `rad/id` and
`rad/self` for each tracked peer.

Signed-off-by: Fintan Halpenny <[email protected]>
  • Loading branch information
FintanH committed Jun 25, 2021
1 parent 6e21a18 commit a98218d
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 14 deletions.
56 changes: 42 additions & 14 deletions librad/src/git/replication.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use super::{
refs::{self, Refs},
storage::{self, ReadOnlyStorage, Storage},
tracking,
types::{reference, Force, Namespace, Reference},
types::{reference, Force, Namespace, One, Reference},
};
use crate::{
identities::git::{Person, Project, Revision, SomeIdentity, VerifiedPerson, VerifiedProject},
Expand Down Expand Up @@ -426,6 +426,40 @@ fn ensure_rad_id(storage: &Storage, urn: &Urn, tip: ext::Oid) -> Result<ext::Oid
id_ref.oid(storage).map(Into::into).map_err(Error::Store)
}

fn adopt_rad_self(storage: &Storage, urn: &Urn, peer: PeerId) -> Result<(), Error> {
let rad_self = Reference::rad_self(Namespace::from(urn), peer);

// We only need to create the rad/id there's a rad/self
if storage.has_ref(&rad_self)? {
if let Some(person) =
identities::person::verify(storage, &unsafe_into_urn(rad_self.clone()))?
{
let rad_id = unsafe_into_urn(Reference::rad_id(Namespace::from(person.urn())));
if !storage.has_urn(&person.urn())? {
ensure_rad_id(storage, &rad_id, person.content_id)?;
symref(storage, &rad_id, rad_self)?;
tracking::track(storage, &rad_id, peer)?;
}
}
}

Ok(())
}

fn symref(storage: &Storage, top_level: &Urn, symbolic: Reference<One>) -> Result<(), Error> {
// Now point our view to the top-level
Reference::try_from(top_level)
.map_err(|e| Error::RefFromUrn {
urn: top_level.clone(),
source: e,
})?
.symbolic_ref::<_, PeerId>(symbolic, Force::False)
.create(storage.as_raw())
.and(Ok(()))
.or_matches(is_exists_err, || Ok(()))
.map_err(|e: git2::Error| Error::Store(e.into()))
}

/// Untrack the list of `PeerId`s, which also has the side-effect of removing
/// that peer's remote references in the storage.
///
Expand Down Expand Up @@ -531,6 +565,7 @@ mod person {
for peer_id in delegations.iter() {
if peer_id != local_peer {
tracking::track(storage, &urn, *peer_id)?;
adopt_rad_self(storage, &urn, *peer_id)?;
}
}

Expand Down Expand Up @@ -648,6 +683,7 @@ mod project {
for peer in tracked {
if peer != *local_peer {
tracking::track(&storage, &urn, peer)?;
adopt_rad_self(storage, &urn, peer)?;
}
}

Expand Down Expand Up @@ -776,19 +812,11 @@ mod project {
tracking::track(storage, &project_urn, peer)?;

// Now point our view to the top-level
Reference::try_from(&delegate_urn)
.map_err(|e| Error::RefFromUrn {
urn: delegate_urn.clone(),
source: e,
})?
.symbolic_ref::<_, PeerId>(
Reference::rad_delegate(Namespace::from(project_urn), &delegate_urn),
Force::False,
)
.create(storage.as_raw())
.and(Ok(()))
.or_matches(is_exists_err, || Ok(()))
.map_err(|e: git2::Error| Error::Store(e.into()))
symref(
storage,
&delegate_urn,
Reference::rad_delegate(Namespace::from(project_urn), &delegate_urn),
)
}

/// Track all direct delegations of a `Project`.
Expand Down
49 changes: 49 additions & 0 deletions test/src/test/integration/daemon/replication.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,3 +466,52 @@ fn track_peer() -> Result<(), anyhow::Error> {
Ok(())
})
}

#[test]
fn replication_includes_user() -> Result<(), anyhow::Error> {
logging::init();

let mut harness = Harness::new();
let alice = harness.add_peer("alice", RunConfig::default(), &[])?;
let bob = harness.add_peer(
"bob",
RunConfig::default(),
&[Seed {
addrs: alice.listen_addrs.clone(),
peer_id: alice.peer_id,
}],
)?;
harness.enter(async move {
let project = state::init_project(
&alice.peer,
&alice.owner,
shia_le_pathbuf(alice.path.join("radicle")),
)
.await?;

state::clone_project(
&bob.peer,
project.urn(),
alice.peer_id,
alice.listen_addrs.clone(),
None,
)
.await?;

state::track(&alice.peer, project.urn(), bob.peer_id).await?;
state::fetch(
&alice.peer,
project.urn(),
bob.peer_id,
bob.listen_addrs.clone(),
None,
)
.await?;

let bob_malkovich = state::get_user(&alice.peer, bob.owner.urn()).await?;

assert_eq!(bob_malkovich, Some(bob.owner.into_inner().into_inner()));

Ok(())
})
}

0 comments on commit a98218d

Please sign in to comment.