#![allow(clippy::too_many_arguments)] use std::collections::{BTreeMap, BTreeSet, HashMap}; use std::fmt; use std::ops::Deref; use std::ops::Range; use std::path::PathBuf; use std::str::FromStr; use amplify::Wrapper; use once_cell::sync::Lazy; use serde::ser::SerializeStruct; use serde::{Deserialize, Serialize}; use thiserror::Error; use crate::cob; use crate::cob::common::{Author, Label, Reaction, Timestamp}; use crate::cob::store::Transaction; use crate::cob::store::{FromHistory as _, HistoryAction}; use crate::cob::thread; use crate::cob::thread::Thread; use crate::cob::thread::{Comment, CommentId}; use crate::cob::{store, ActorId, EntryId, ObjectId, TypeName}; use crate::crypto::{PublicKey, Signer}; use crate::git; use crate::identity; use crate::identity::doc::DocError; use crate::identity::PayloadError; use crate::prelude::*; use crate::storage; /// Type name of a patch. pub static TYPENAME: Lazy = Lazy::new(|| FromStr::from_str("xyz.radicle.patch").expect("type name is valid")); /// Patch operation. pub type Op = cob::Op; /// Identifier for a patch. pub type PatchId = ObjectId; /// Unique identifier for a patch revision. #[derive( Wrapper, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, From, Display, )] #[display(inner)] #[wrap(Deref)] pub struct RevisionId(EntryId); /// Unique identifier for a patch review. #[derive( Wrapper, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, From, Display, )] #[display(inner)] #[wrapper(Deref)] pub struct ReviewId(EntryId); /// Index of a revision in the revisions list. pub type RevisionIx = usize; /// Error applying an operation onto a state. #[derive(Debug, Error)] pub enum Error { /// Error trying to delete the protected root revision. #[error("refusing to delete root revision: {0}")] RootRevision(RevisionId), /// Causal dependency missing. /// /// This error indicates that the operations are not being applied /// in causal order, which is a requirement for this CRDT. /// /// For example, this can occur if an operation references anothern operation /// that hasn't happened yet. #[error("causal dependency {0:?} missing")] Missing(EntryId), /// Error applying an op to the patch thread. #[error("thread apply failed: {0}")] Thread(#[from] thread::Error), /// Error loading the identity document committed to by an operation. #[error("identity doc failed to load: {0}")] Doc(#[from] DocError), /// Error loading the document payload. #[error("payload failed to load: {0}")] Payload(#[from] PayloadError), /// The merge operation is invalid. #[error("invalid merge operation in {0}")] InvalidMerge(EntryId), /// Git error. #[error("git: {0}")] Git(#[from] git::ext::Error), /// Validation error. #[error("validation failed: {0}")] Validate(&'static str), /// Store error. #[error("store: {0}")] Store(#[from] store::Error), } /// Patch operation. #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] #[serde(tag = "type", rename_all = "camelCase")] pub enum Action { // // Actions on patch. // #[serde(rename = "edit")] Edit { title: String, target: MergeTarget }, #[serde(rename = "label")] Label { labels: BTreeSet