haematite 0.6.2

Content-addressed, branchable, actor-native storage engine
Documentation
use std::fmt;

use crate::tree::{Hash, TreeError};

use super::handle::BranchError;
use super::merge::MergeError;
use super::policy::BranchPolicyError;
use super::refstore::BranchRefError;

/// Errors raised by branch commit, merge, and named-branch lifecycle paths.
#[derive(Debug)]
pub enum BranchCommitError {
    /// The handle holds no registry guard, so advancing it would race prune.
    Unregistered,
    /// An operation requiring durable identity received an anonymous handle.
    UnnamedBranch,
    /// Parent links were supplied for a volatile commit, which has no record.
    VolatileExtraParents,
    /// A fork-by-hash anchor has no live or durable protection.
    UnprotectedAnchor {
        /// The refused anchor root.
        root: Hash,
    },
    /// A kind or Namespace-lineage boundary refused a fork or merge.
    Policy(BranchPolicyError),
    /// A branch-handle operation failed.
    Branch(BranchError),
    /// Materialising a shard buffer into the shared tree failed.
    Tree(TreeError),
    /// Three-way content merge failed after branch policy accepted it.
    Merge(MergeError),
    /// The store's dirty-directory barrier failed before durable install.
    Barrier(String),
    /// The durable ref store refused or failed an operation.
    Ref(BranchRefError),
}

impl fmt::Display for BranchCommitError {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Unregistered => write!(
                formatter,
                "branch handle is not registered against a branch registry; \
                 fork it via a registering constructor before committing"
            ),
            Self::UnnamedBranch => write!(
                formatter,
                "operation requires a named branch handle from create_branch/open_branch"
            ),
            Self::VolatileExtraParents => write!(
                formatter,
                "extra parents require a durable commit: volatile commits install no record to carry them"
            ),
            Self::UnprotectedAnchor { root } => write!(
                formatter,
                "fork anchor {root} is protected by no live branch, no named branch record, and \
                 no named snapshot, so a prune could reclaim it at any moment; name a snapshot \
                 at this root first (SnapshotRegistry::name), then fork"
            ),
            Self::Policy(error) => error.fmt(formatter),
            Self::Branch(error) => write!(formatter, "branch commit handle error: {error}"),
            Self::Tree(error) => write!(formatter, "branch commit tree error: {error}"),
            Self::Merge(error) => write!(formatter, "branch merge error: {error}"),
            Self::Barrier(reason) => {
                write!(
                    formatter,
                    "branch commit durability barrier failed: {reason}"
                )
            }
            Self::Ref(error) => write!(formatter, "branch commit ref store error: {error}"),
        }
    }
}

impl std::error::Error for BranchCommitError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Self::Policy(error) => Some(error),
            Self::Branch(error) => Some(error),
            Self::Tree(error) => Some(error),
            Self::Merge(error) => Some(error),
            Self::Ref(error) => Some(error),
            Self::Unregistered
            | Self::UnnamedBranch
            | Self::VolatileExtraParents
            | Self::UnprotectedAnchor { .. }
            | Self::Barrier(_) => None,
        }
    }
}

impl From<BranchError> for BranchCommitError {
    fn from(error: BranchError) -> Self {
        Self::Branch(error)
    }
}

impl From<TreeError> for BranchCommitError {
    fn from(error: TreeError) -> Self {
        Self::Tree(error)
    }
}

impl From<MergeError> for BranchCommitError {
    fn from(error: MergeError) -> Self {
        Self::Merge(error)
    }
}

impl From<BranchPolicyError> for BranchCommitError {
    fn from(error: BranchPolicyError) -> Self {
        Self::Policy(error)
    }
}

impl From<BranchRefError> for BranchCommitError {
    fn from(error: BranchRefError) -> Self {
        Self::Ref(error)
    }
}