Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
Move `Change` from `radicle-crdt` to `radicle`
Alexis Sellier committed 3 years ago
commit e8a2432f9dd41b4f56fdabdfbff57d8d45e33500
parent f6e8a18b15d0d934f0b9ed0b2cdcd437ac47e8fa
10 files changed +119 -134
modified Cargo.lock
@@ -2249,12 +2249,10 @@ version = "0.1.0"
dependencies = [
 "fastrand",
 "num-traits",
-
 "olpc-cjson",
 "quickcheck",
 "quickcheck_macros",
 "radicle-crypto",
 "serde",
-
 "serde_json",
 "tempfile",
]

modified radicle-crdt/Cargo.toml
@@ -9,10 +9,8 @@ test = ["fastrand", "quickcheck"]
[dependencies]
fastrand = { version = "1.8.0", optional = true }
num-traits = { version = "0.2.15", default-features = false, features = ["std"] }
-
olpc-cjson = { version = "0.1.1" }
quickcheck = { version = "1", optional = true }
serde = { version = "1" }
-
serde_json = { version = "1" }

[dependencies.radicle-crypto]
path = "../radicle-crypto"
deleted radicle-crdt/src/change.rs
@@ -1,110 +0,0 @@
-
use std::collections::BTreeMap;
-

-
use radicle_crypto::{PublicKey, Signer};
-
use serde::{Deserialize, Serialize};
-

-
use crate::clock;
-
use crate::clock::Lamport;
-

-
/// Identifies a change.
-
pub type ChangeId = (Lamport, ActorId);
-
/// The author of a change.
-
pub type ActorId = PublicKey;
-

-
/// The `Change` is the unit of replication.
-
/// Everything that can be done in the system is represented by a `Change` object.
-
/// Changes are applied to an accumulator to yield a final state.
-
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
-
pub struct Change<A> {
-
    /// The action carried out by this change.
-
    pub action: A,
-
    /// The author of the change.
-
    pub author: ActorId,
-
    /// Lamport clock.
-
    pub clock: Lamport,
-
    /// Timestamp of this change.
-
    pub timestamp: clock::Physical,
-
}
-

-
impl<A> Change<A> {
-
    /// Get the change id.
-
    pub fn id(&self) -> ChangeId {
-
        (self.clock, self.author)
-
    }
-
}
-

-
impl<A: Serialize> Change<A> {
-
    /// Serialize the change into a byte string.
-
    pub fn encode(&self) -> Vec<u8> {
-
        let mut buf = Vec::new();
-
        let mut serializer =
-
            serde_json::Serializer::with_formatter(&mut buf, olpc_cjson::CanonicalFormatter::new());
-

-
        self.serialize(&mut serializer).unwrap();
-

-
        buf
-
    }
-
}
-

-
impl<'de, A: Deserialize<'de>> Change<A> {
-
    /// Deserialize a change from a byte string.
-
    pub fn decode(bytes: &'de [u8]) -> Result<Self, serde_json::Error> {
-
        serde_json::from_slice(bytes)
-
    }
-
}
-

-
/// An object that can be used to create and sign changes.
-
#[derive(Default)]
-
pub struct Actor<G, A> {
-
    pub signer: G,
-
    pub clock: Lamport,
-
    pub changes: BTreeMap<(Lamport, PublicKey), Change<A>>,
-
}
-

-
impl<G: Signer, A: Clone + Serialize> Actor<G, A> {
-
    pub fn new(signer: G) -> Self {
-
        Self {
-
            signer,
-
            clock: Lamport::default(),
-
            changes: BTreeMap::default(),
-
        }
-
    }
-

-
    pub fn receive(&mut self, changes: impl IntoIterator<Item = Change<A>>) -> Lamport {
-
        for change in changes {
-
            let clock = change.clock;
-

-
            self.changes.insert((clock, change.author), change);
-
            self.clock.merge(clock);
-
        }
-
        self.clock
-
    }
-

-
    /// Reset actor state to initial state.
-
    pub fn reset(&mut self) {
-
        self.changes.clear();
-
        self.clock = Lamport::default();
-
    }
-

-
    /// Returned an ordered list of events.
-
    pub fn timeline(&self) -> impl Iterator<Item = &Change<A>> {
-
        self.changes.values()
-
    }
-

-
    /// Create a new change.
-
    pub fn change(&mut self, action: A) -> Change<A> {
-
        let author = *self.signer.public_key();
-
        let clock = self.clock;
-
        let timestamp = clock::Physical::now();
-
        let change = Change {
-
            action,
-
            author,
-
            clock,
-
            timestamp,
-
        };
-
        self.changes.insert((self.clock, author), change.clone());
-
        self.clock.tick();
-

-
        change
-
    }
-
}
modified radicle-crdt/src/lib.rs
@@ -2,7 +2,6 @@
#![allow(clippy::bool_assert_comparison)]
#![allow(clippy::collapsible_else_if)]
#![allow(clippy::type_complexity)]
-
pub mod change;
pub mod clock;
pub mod gmap;
pub mod lwwmap;
@@ -16,7 +15,6 @@ pub mod test;

////////////////////////////////////////////////////////////////////////////////

-
pub use change::*;
pub use clock::Lamport;
pub use gmap::GMap;
pub use lwwmap::LWWMap;
modified radicle-crdt/src/ord.rs
@@ -68,6 +68,7 @@ impl<T: Bounded> Bounded for Max<T> {

#[allow(clippy::derive_ord_xor_partial_ord)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, Serialize, Deserialize)]
+
#[serde(transparent)]
pub struct Min<T>(pub T);

impl<T> Default for Min<T>
modified radicle/src/cob.rs
@@ -1,9 +1,11 @@
+
pub mod change;
pub mod common;
pub mod issue;
pub mod patch;
pub mod store;
pub mod thread;

+
pub use change::{Actor, ActorId, Change, ChangeId};
pub use cob::{
    identity, object::collaboration::error, CollaborativeObject, Contents, Create, Entry, History,
    ObjectId, TypeName, Update,
added radicle/src/cob/change.rs
@@ -0,0 +1,96 @@
+
use std::collections::BTreeMap;
+

+
use radicle_crdt::clock;
+
use radicle_crdt::clock::Lamport;
+
use radicle_crypto::{PublicKey, Signer};
+
use serde::{Deserialize, Serialize};
+

+
/// Identifies a change.
+
pub type ChangeId = (Lamport, ActorId);
+
/// The author of a change.
+
pub type ActorId = PublicKey;
+

+
/// The `Change` is the unit of replication.
+
/// Everything that can be done in the system is represented by a `Change` object.
+
/// Changes are applied to an accumulator to yield a final state.
+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+
pub struct Change<A> {
+
    /// The action carried out by this change.
+
    pub action: A,
+
    /// The author of the change.
+
    pub author: ActorId,
+
    /// Lamport clock.
+
    pub clock: Lamport,
+
    /// Timestamp of this change.
+
    pub timestamp: clock::Physical,
+
}
+

+
impl<A> Change<A> {
+
    /// Get the change id.
+
    pub fn id(&self) -> ChangeId {
+
        (self.clock, self.author)
+
    }
+
}
+

+
impl<'de, A: Deserialize<'de>> Change<A> {
+
    /// Deserialize a change from a byte string.
+
    pub fn decode(bytes: &'de [u8]) -> Result<Self, serde_json::Error> {
+
        serde_json::from_slice(bytes)
+
    }
+
}
+

+
/// An object that can be used to create and sign changes.
+
#[derive(Default)]
+
pub struct Actor<G, A> {
+
    pub signer: G,
+
    pub clock: Lamport,
+
    pub changes: BTreeMap<(Lamport, PublicKey), Change<A>>,
+
}
+

+
impl<G: Signer, A: Clone + Serialize> Actor<G, A> {
+
    pub fn new(signer: G) -> Self {
+
        Self {
+
            signer,
+
            clock: Lamport::default(),
+
            changes: BTreeMap::default(),
+
        }
+
    }
+

+
    pub fn receive(&mut self, changes: impl IntoIterator<Item = Change<A>>) -> Lamport {
+
        for change in changes {
+
            let clock = change.clock;
+

+
            self.changes.insert((clock, change.author), change);
+
            self.clock.merge(clock);
+
        }
+
        self.clock
+
    }
+

+
    /// Reset actor state to initial state.
+
    pub fn reset(&mut self) {
+
        self.changes.clear();
+
        self.clock = Lamport::default();
+
    }
+

+
    /// Returned an ordered list of events.
+
    pub fn timeline(&self) -> impl Iterator<Item = &Change<A>> {
+
        self.changes.values()
+
    }
+

+
    /// Create a new change.
+
    pub fn change(&mut self, action: A) -> Change<A> {
+
        let author = *self.signer.public_key();
+
        let clock = self.clock;
+
        let timestamp = clock::Physical::now();
+
        let change = Change {
+
            action,
+
            author,
+
            clock,
+
            timestamp,
+
        };
+
        self.changes.insert((self.clock, author), change.clone());
+
        self.clock.tick();
+

+
        change
+
    }
+
}
modified radicle/src/cob/issue.rs
@@ -2,20 +2,21 @@ use std::ops::{ControlFlow, Deref};
use std::str::FromStr;

use once_cell::sync::Lazy;
-
use radicle_crdt as crdt;
use radicle_crdt::clock;
-
use radicle_crdt::{ChangeId, LWWReg, LWWSet, Max, Semilattice};
+
use radicle_crdt::{LWWReg, LWWSet, Max, Semilattice};
use serde::{Deserialize, Serialize};
use thiserror::Error;

+
use crate::cob;
use crate::cob::common::{Author, Reaction, Tag};
use crate::cob::thread;
use crate::cob::thread::{CommentId, Thread};
-
use crate::cob::{store, ObjectId, TypeName};
+
use crate::cob::{store, ChangeId, ObjectId, TypeName};
use crate::crypto::{PublicKey, Signer};
use crate::storage::git as storage;

-
pub type Change = crdt::Change<Action>;
+
/// Issue change.
+
pub type Change = crate::cob::Change<Action>;

/// Type name of an issue.
pub static TYPENAME: Lazy<TypeName> =
@@ -175,7 +176,7 @@ impl Issue {
                }
            }
            Action::Thread { action } => {
-
                self.thread.apply([crdt::Change {
+
                self.thread.apply([cob::Change {
                    action,
                    author: change.author,
                    clock: change.clock,
modified radicle/src/cob/patch.rs
@@ -6,17 +6,17 @@ use std::ops::Range;
use std::str::FromStr;

use once_cell::sync::Lazy;
-
use radicle_crdt as crdt;
use radicle_crdt::clock;
-
use radicle_crdt::{ActorId, ChangeId, GMap, LWWReg, LWWSet, Max, Redactable, Semilattice};
+
use radicle_crdt::{GMap, LWWReg, LWWSet, Max, Redactable, Semilattice};
use serde::{Deserialize, Serialize};
use thiserror::Error;

+
use crate::cob;
use crate::cob::common::{Author, Tag, Timestamp};
use crate::cob::thread;
use crate::cob::thread::CommentId;
use crate::cob::thread::Thread;
-
use crate::cob::{store, ObjectId, TypeName};
+
use crate::cob::{store, ActorId, ChangeId, ObjectId, TypeName};
use crate::crypto::{PublicKey, Signer};
use crate::git;
use crate::prelude::*;
@@ -30,7 +30,7 @@ pub static TYPENAME: Lazy<TypeName> =
    Lazy::new(|| FromStr::from_str("xyz.radicle.patch").expect("type name is valid"));

/// Patch change.
-
pub type Change = crdt::Change<Action>;
+
pub type Change = crate::cob::Change<Action>;

/// Identifier for a patch.
pub type PatchId = ObjectId;
@@ -306,7 +306,7 @@ impl Patch {
                // TODO(cloudhead): Make sure we can deal with redacted revisions which are added
                // to out of order, like in the `Merge` case.
                if let Some(Redactable::Present(revision)) = self.revisions.get_mut(&revision) {
-
                    revision.discussion.apply([crdt::Change {
+
                    revision.discussion.apply([cob::Change {
                        action,
                        author: change.author,
                        clock: change.clock,
@@ -786,13 +786,13 @@ mod test {
    use std::str::FromStr;
    use std::{array, iter};

-
    use crdt::test::{assert_laws, WeightedGenerator};
-
    use crdt::{Actor, ActorId};
+
    use radicle_crdt::test::{assert_laws, WeightedGenerator};

    use pretty_assertions::assert_eq;
    use quickcheck::{Arbitrary, TestResult};

    use super::*;
+
    use crate::cob::change::{Actor, ActorId};
    use crate::crypto::test::signer::MockSigner;
    use crate::test;

modified radicle/src/cob/thread.rs
@@ -8,15 +8,16 @@ use once_cell::sync::Lazy;
use radicle_crdt as crdt;
use serde::{Deserialize, Serialize};

+
use crate::cob;
use crate::cob::common::{Reaction, Timestamp};
use crate::cob::store;
-
use crate::cob::{History, TypeName};
+
use crate::cob::{ActorId, Change, ChangeId, History, TypeName};
use crate::crypto::Signer;

use crdt::clock::Lamport;
use crdt::lwwset::LWWSet;
use crdt::redactable::Redactable;
-
use crdt::{ActorId, Change, ChangeId, Semilattice};
+
use crdt::Semilattice;

/// Type name of a thread.
pub static TYPENAME: Lazy<TypeName> =
@@ -244,13 +245,13 @@ impl Thread {

/// An object that can be used to create and sign changes.
pub struct Actor<G> {
-
    inner: crdt::Actor<G, Action>,
+
    inner: cob::Actor<G, Action>,
}

impl<G: Default + Signer> Default for Actor<G> {
    fn default() -> Self {
        Self {
-
            inner: crdt::Actor::new(G::default()),
+
            inner: cob::Actor::new(G::default()),
        }
    }
}
@@ -258,7 +259,7 @@ impl<G: Default + Signer> Default for Actor<G> {
impl<G: Signer> Actor<G> {
    pub fn new(signer: G) -> Self {
        Self {
-
            inner: crdt::Actor::new(signer),
+
            inner: cob::Actor::new(signer),
        }
    }

@@ -282,7 +283,7 @@ impl<G: Signer> Actor<G> {
}

impl<G> Deref for Actor<G> {
-
    type Target = crdt::Actor<G, Action>;
+
    type Target = cob::Actor<G, Action>;

    fn deref(&self) -> &Self::Target {
        &self.inner