jj-cz 1.1.0

Conventional commits for Jujutsu
Documentation
use jj_lib::revset::{RevsetEvaluationError, RevsetParseError, RevsetResolutionError};

use crate::commit::types::{CommitMessageError, DescriptionError, ScopeError};

#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum Error {
    // Domain errors
    #[error("Invalid scope: {0}")]
    InvalidScope(String),
    #[error("Invalid description: {0}")]
    InvalidDescription(String),
    #[error("Invalid commit message: {0}")]
    InvalidCommitMessage(String),
    // Infrastructure errors
    #[error("Not a Jujutsu repository")]
    NotARepository,
    #[error("Repository operation failed: {context}")]
    JjOperation { context: String },
    #[error("Repository is locked by another process")]
    RepositoryLocked,
    #[error("Could not get current directory")]
    FailedGettingCurrentDir,
    #[error("Could not load Jujutsu configuration: {context}")]
    FailedReadingConfig { context: String },
    // Application errors
    #[error("Operation cancelled by user")]
    Cancelled,
    #[error("Non-interactive terminal detected")]
    NonInteractive,
    #[error("Failed to resolve revision '{revset}': {context}")]
    RevsetResolutionError { revset: String, context: String },
    #[error("Revision set '{revset}' resolves to multiple commits; specify a single revision")]
    MultipleRevisions { revset: String },
    #[error("--new cannot be used with multiple revisions")]
    NewFlagWithMultipleRevisions,
}

impl From<ScopeError> for Error {
    fn from(value: ScopeError) -> Self {
        Self::InvalidScope(value.to_string())
    }
}

impl From<DescriptionError> for Error {
    fn from(value: DescriptionError) -> Self {
        Self::InvalidDescription(value.to_string())
    }
}

impl From<CommitMessageError> for Error {
    fn from(value: CommitMessageError) -> Self {
        Self::InvalidCommitMessage(value.to_string())
    }
}

impl From<std::io::Error> for Error {
    fn from(_: std::io::Error) -> Self {
        Self::FailedGettingCurrentDir
    }
}

impl<T> From<std::sync::PoisonError<T>> for Error {
    fn from(_: std::sync::PoisonError<T>) -> Self {
        Self::JjOperation {
            context: "internal lock poisoned".to_string(),
        }
    }
}

impl Error {
    pub fn from_revset_parse_error(revset: &str, error: RevsetParseError) -> Self {
        Self::RevsetResolutionError {
            revset: revset.to_string(),
            context: error.to_string(),
        }
    }

    pub fn from_revset_resolution_error(revset: &str, error: RevsetResolutionError) -> Self {
        Self::RevsetResolutionError {
            revset: revset.to_string(),
            context: error.to_string(),
        }
    }

    pub fn from_revset_evaluation_error(revset: &str, error: RevsetEvaluationError) -> Self {
        Self::RevsetResolutionError {
            revset: revset.to_string(),
            context: error.to_string(),
        }
    }
}