Skip to main content

eggup_core/
error.rs

1use std::fmt;
2use std::io;
3
4/// The result type used by eggup-core.
5pub type Result<T> = std::result::Result<T, Error>;
6
7/// Errors produced while validating a local update plan or preparing private stage state.
8#[derive(Debug)]
9pub enum Error {
10    /// A caller supplied a value that violates a core invariant.
11    InvalidInput(String),
12    /// The requested member was not present in the artifact set.
13    UnknownMember(String),
14    /// An owned filesystem operation failed.
15    Io {
16        /// The operation being performed.
17        operation: &'static str,
18        /// The underlying operating-system error.
19        source: io::Error,
20    },
21    /// Another process or an ambiguous lock record owns the installation domain.
22    UpdateInProgress {
23        /// The lock path that prevented acquisition.
24        lock: std::path::PathBuf,
25    },
26    /// A live destination failed the immediate pre-mutation ownership check.
27    DestinationConflict {
28        /// The destination path that failed revalidation.
29        destination: std::path::PathBuf,
30    },
31    /// Declared integrity or candidate identity evidence did not pass.
32    VerificationFailed(String),
33    /// Candidate execution could not produce an accepted bounded result.
34    CandidateExecution(String),
35}
36
37impl Error {
38    pub(crate) fn invalid(message: impl Into<String>) -> Self {
39        Self::InvalidInput(message.into())
40    }
41
42    pub(crate) fn io(operation: &'static str, source: io::Error) -> Self {
43        Self::Io { operation, source }
44    }
45}
46
47impl fmt::Display for Error {
48    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
49        match self {
50            Self::InvalidInput(message) => write!(formatter, "invalid update input: {message}"),
51            Self::UnknownMember(member) => write!(formatter, "unknown artifact member: {member}"),
52            Self::Io { operation, source } => write!(formatter, "{operation}: {source}"),
53            Self::UpdateInProgress { lock } => {
54                write!(
55                    formatter,
56                    "installation update already in progress: {}",
57                    lock.display()
58                )
59            }
60            Self::DestinationConflict { destination } => write!(
61                formatter,
62                "destination failed ownership revalidation: {}",
63                destination.display()
64            ),
65            Self::VerificationFailed(message) => {
66                write!(formatter, "verification failed: {message}")
67            }
68            Self::CandidateExecution(message) => {
69                write!(formatter, "candidate execution failed: {message}")
70            }
71        }
72    }
73}
74
75impl std::error::Error for Error {
76    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
77        match self {
78            Self::Io { source, .. } => Some(source),
79            Self::InvalidInput(_)
80            | Self::UnknownMember(_)
81            | Self::UpdateInProgress { .. }
82            | Self::DestinationConflict { .. }
83            | Self::VerificationFailed(_)
84            | Self::CandidateExecution(_) => None,
85        }
86    }
87}