use std::path::PathBuf;
use thiserror::Error;
pub type ChangesetResult<T> = Result<T, ChangesetError>;
#[derive(Debug, Error, Clone)]
pub enum ChangesetError {
#[error("Changeset not found for branch '{branch}'")]
NotFound {
branch: String,
},
#[error("Invalid branch name '{branch}': {reason}")]
InvalidBranch {
branch: String,
reason: String,
},
#[error("Changeset validation failed")]
ValidationFailed {
errors: Vec<String>,
},
#[error("Changeset storage error at '{path}': {reason}")]
StorageError {
path: PathBuf,
reason: String,
},
#[error("Failed to {operation} changeset data: {reason}")]
SerializationError {
operation: String,
reason: String,
},
#[error("Changeset already exists for branch '{branch}' at '{path}'")]
AlreadyExists {
branch: String,
path: PathBuf,
},
#[error("Git operation failed: {operation} - {reason}")]
GitError {
operation: String,
reason: String,
},
#[error("Failed to archive changeset for branch '{branch}': {reason}")]
ArchiveError {
branch: String,
reason: String,
},
#[error("Invalid changeset ID '{id}': {reason}")]
InvalidId {
id: String,
reason: String,
},
#[error("Package '{package}' not found in changeset for branch '{branch}'")]
PackageNotInChangeset {
branch: String,
package: String,
},
#[error("Invalid environment '{environment}': not in available environments {available:?}")]
InvalidEnvironment {
environment: String,
available: Vec<String>,
},
#[error("Changeset for branch '{branch}' is empty (no packages)")]
EmptyChangeset {
branch: String,
},
#[error("Commit '{commit}' not found in repository")]
CommitNotFound {
commit: String,
},
#[error("Invalid commit hash '{commit}': {reason}")]
InvalidCommit {
commit: String,
reason: String,
},
#[error("Failed to query changeset history: {reason}")]
HistoryQueryFailed {
reason: String,
},
#[error("Permission denied for changeset operation at '{path}': {operation}")]
PermissionDenied {
path: PathBuf,
operation: String,
},
#[error(
"Concurrent modification detected for changeset '{branch}': expected timestamp {expected}, found {actual}"
)]
ConcurrentModification {
branch: String,
expected: String,
actual: String,
},
#[error("Invalid changeset path configuration '{path}': {reason}")]
InvalidPath {
path: PathBuf,
reason: String,
},
#[error("Failed to lock changeset for branch '{branch}': {reason}")]
LockFailed {
branch: String,
reason: String,
},
#[error("Git integration failed during {operation}: {reason}")]
GitIntegration {
operation: String,
reason: String,
},
}
impl AsRef<str> for ChangesetError {
fn as_ref(&self) -> &str {
match self {
Self::NotFound { .. } => "changeset not found",
Self::InvalidBranch { .. } => "invalid branch name",
Self::ValidationFailed { .. } => "changeset validation failed",
Self::StorageError { .. } => "changeset storage error",
Self::SerializationError { .. } => "changeset serialization error",
Self::AlreadyExists { .. } => "changeset already exists",
Self::GitError { .. } => "git error",
Self::ArchiveError { .. } => "changeset archive error",
Self::InvalidId { .. } => "invalid changeset id",
Self::PackageNotInChangeset { .. } => "package not in changeset",
Self::InvalidEnvironment { .. } => "invalid environment",
Self::EmptyChangeset { .. } => "empty changeset",
Self::CommitNotFound { .. } => "commit not found",
Self::InvalidCommit { .. } => "invalid commit",
Self::HistoryQueryFailed { .. } => "history query failed",
Self::PermissionDenied { .. } => "permission denied",
Self::ConcurrentModification { .. } => "concurrent modification",
Self::InvalidPath { .. } => "invalid changeset path",
Self::LockFailed { .. } => "lock failed",
Self::GitIntegration { .. } => "git integration error",
}
}
}
impl ChangesetError {
#[must_use]
pub fn count(&self) -> usize {
match self {
Self::ValidationFailed { errors } => errors.len(),
_ => 1,
}
}
#[must_use]
pub fn errors(&self) -> String {
match self {
Self::ValidationFailed { errors } => {
errors.iter().map(|e| format!(" - {}", e)).collect::<Vec<_>>().join("\n")
}
_ => self.to_string(),
}
}
#[must_use]
pub fn is_transient(&self) -> bool {
matches!(
self,
Self::LockFailed { .. }
| Self::ConcurrentModification { .. }
| Self::StorageError { .. }
| Self::GitError { .. }
)
}
}