Files
sasedev-knowledge/crates/knowledge-git-lib/src/error.rs
2026-09-29 13:57:45 +02:00

151 lines
8.5 KiB
Rust

// file: crates/knowledge-git-lib/src/error.rs
// version: 5
//! Recoverable errors for controlled Git process execution.
/// Git operation category safe to expose in diagnostics.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum GitOperation {
/// Clone one configured source into a controlled mirror.
CloneMirror,
/// Inspect whether a controlled repository is a valid bare mirror.
InspectMirror,
/// Refresh refs in one controlled mirror.
RefreshMirror,
/// Resolve one configured reference to a commit revision.
ResolveRevision,
/// Materialize one detached revision-addressed snapshot.
CreateSnapshot,
/// Validate an existing detached snapshot before reuse.
InspectSnapshot,
/// Create one isolated detached worktree for candidate construction.
CreateWriteWorktree,
/// Stage the requested candidate mutations.
StageCandidate,
/// Inspect the candidate index, commit or parent relationship.
InspectCandidate,
/// Create the candidate commit with explicit identity.
CommitCandidate,
/// Retain the detached candidate commit under an internal backend reference.
PreserveCandidate,
/// Remove one backend-owned candidate worktree.
RemoveWriteWorktree,
/// Observe the current state of one remote branch.
InspectRemote,
/// Push one candidate revision with an explicit compare-and-exchange guard.
PushCandidate,
}
impl std::fmt::Display for crate::GitOperation {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
crate::GitOperation::CloneMirror => return formatter.write_str("clone mirror"),
crate::GitOperation::InspectMirror => return formatter.write_str("inspect mirror"),
crate::GitOperation::RefreshMirror => return formatter.write_str("refresh mirror"),
crate::GitOperation::ResolveRevision => return formatter.write_str("resolve revision"),
crate::GitOperation::CreateSnapshot => return formatter.write_str("create snapshot"),
crate::GitOperation::InspectSnapshot => return formatter.write_str("inspect snapshot"),
crate::GitOperation::CreateWriteWorktree => return formatter.write_str("create write worktree"),
crate::GitOperation::StageCandidate => return formatter.write_str("stage candidate"),
crate::GitOperation::InspectCandidate => return formatter.write_str("inspect candidate"),
crate::GitOperation::CommitCandidate => return formatter.write_str("commit candidate"),
crate::GitOperation::PreserveCandidate => return formatter.write_str("preserve candidate"),
crate::GitOperation::RemoveWriteWorktree => return formatter.write_str("remove write worktree"),
crate::GitOperation::InspectRemote => return formatter.write_str("inspect remote branch"),
crate::GitOperation::PushCandidate => return formatter.write_str("push guarded candidate"),
}
}
}
/// Recoverable error returned by the controlled Git backend.
///
/// Process failures intentionally retain only an operation category and exit code. Source URLs,
/// command arguments, stderr and credentials are not embedded in this public error.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum GitBackendError {
/// The configured Git executable path is empty.
EmptyGitExecutable,
/// The configured state root is empty.
EmptyStateRoot,
/// A local source path or remote source string is empty.
EmptySourceLocation,
/// One logical source identifier was registered more than once in the same backend.
DuplicateSource,
/// No physical source configuration is registered for the requested logical source.
SourceNotConfigured,
/// The backend could not prepare its generated-state directories.
StatePreparationFailed,
/// The Git executable could not be started for the requested operation.
GitUnavailable {
/// Operation that could not start.
operation: crate::GitOperation,
},
/// Git returned a non-success status for the requested operation.
GitCommandFailed {
/// Operation that failed.
operation: crate::GitOperation,
/// Process exit code when the operating system exposed one.
exit_code: Option<i32>,
},
/// An existing controlled repository is not a valid bare mirror.
InvalidMirror,
/// A controlled mirror required by a read operation does not exist yet.
MirrorMissing,
/// A revision supplied to snapshot materialization is not a safe Git object identity.
InvalidRevision,
/// An existing snapshot does not match the requested revision or is not clean.
InvalidSnapshot,
/// The deterministic backend-owned write worktree path already exists unexpectedly.
WriteWorktreeExists,
/// A mutation would traverse or replace a symbolic link.
UnsafeMutationTarget,
/// A requested deletion target does not exist.
MutationTargetMissing,
/// A filesystem mutation or parent-directory preparation failed.
MutationFilesystemFailed,
/// The staged candidate paths do not exactly match the requested mutation set.
CandidateMutationMismatch,
/// The resulting candidate commit does not have the requested base as its sole first parent.
InvalidCandidate,
/// A backend-owned write worktree could not be removed deterministically.
WriteCleanupFailed,
/// Git returned output that does not satisfy the backend contract.
UnexpectedGitOutput {
/// Operation whose output could not be validated.
operation: crate::GitOperation,
},
}
impl std::fmt::Display for crate::GitBackendError {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
crate::GitBackendError::EmptyGitExecutable => return formatter.write_str("git executable must not be empty"),
crate::GitBackendError::EmptyStateRoot => return formatter.write_str("git state root must not be empty"),
crate::GitBackendError::EmptySourceLocation => return formatter.write_str("git source location must not be empty"),
crate::GitBackendError::DuplicateSource => return formatter.write_str("git source identifier is already configured"),
crate::GitBackendError::SourceNotConfigured => return formatter.write_str("git source identifier is not configured"),
crate::GitBackendError::StatePreparationFailed => return formatter.write_str("git state directories could not be prepared"),
crate::GitBackendError::GitUnavailable { operation } => return write!(formatter, "git is unavailable while attempting to {operation}"),
crate::GitBackendError::GitCommandFailed { operation, exit_code } => {
return write!(formatter, "git failed while attempting to {operation}; exit code {exit_code:?}");
},
crate::GitBackendError::InvalidMirror => return formatter.write_str("controlled git repository is not a valid bare mirror"),
crate::GitBackendError::MirrorMissing => return formatter.write_str("controlled git mirror does not exist"),
crate::GitBackendError::InvalidRevision => return formatter.write_str("git revision is not a safe object identity"),
crate::GitBackendError::InvalidSnapshot => return formatter.write_str("controlled git snapshot is invalid or dirty"),
crate::GitBackendError::WriteWorktreeExists => return formatter.write_str("controlled git write worktree already exists"),
crate::GitBackendError::UnsafeMutationTarget => return formatter.write_str("git mutation target traverses a symbolic link"),
crate::GitBackendError::MutationTargetMissing => return formatter.write_str("git deletion target does not exist"),
crate::GitBackendError::MutationFilesystemFailed => return formatter.write_str("git candidate filesystem mutation failed"),
crate::GitBackendError::CandidateMutationMismatch => return formatter.write_str("git candidate staged paths do not match requested mutations"),
crate::GitBackendError::InvalidCandidate => return formatter.write_str("git candidate commit does not match the requested base"),
crate::GitBackendError::WriteCleanupFailed => return formatter.write_str("controlled git write worktree cleanup failed"),
crate::GitBackendError::UnexpectedGitOutput { operation } => {
return write!(formatter, "git returned unexpected output while attempting to {operation}");
},
}
}
}
impl std::error::Error for crate::GitBackendError {}