Skip to main content

zub/
error.rs

1use std::path::PathBuf;
2
3use crate::Hash;
4
5/// error type for zuboperations
6#[derive(Debug, thiserror::Error)]
7pub enum Error {
8    #[error("repository not found at {0}")]
9    NoRepo(PathBuf),
10
11    #[error("repository already exists at {0}")]
12    RepoExists(PathBuf),
13
14    #[error("ref not found: {0}")]
15    RefNotFound(String),
16
17    #[error("invalid ref name: {0}")]
18    InvalidRef(String),
19
20    #[error("path not found in tree: {0}")]
21    PathNotFound(String),
22
23    #[error("object not found: {0}")]
24    ObjectNotFound(Hash),
25
26    #[error("corrupt object: hash mismatch for {0}")]
27    CorruptObject(Hash),
28
29    #[error("path conflict during union: {0}")]
30    UnionConflict(PathBuf),
31
32    #[error("type conflict during union at {path}: cannot merge {first_type} with {second_type}")]
33    UnionTypeConflict {
34        path: PathBuf,
35        first_type: &'static str,
36        second_type: &'static str,
37    },
38
39    #[error("checkout target not empty: {0}")]
40    TargetNotEmpty(PathBuf),
41
42    #[error("lock contention on repository")]
43    LockContention,
44
45    #[error("uid {0} not mapped in namespace")]
46    UnmappedUid(u32),
47
48    #[error("gid {0} not mapped in namespace")]
49    UnmappedGid(u32),
50
51    #[error("failed to parse namespace mapping from {0}")]
52    NamespaceParseError(PathBuf),
53
54    #[error("remote not found: {0}")]
55    RemoteNotFound(String),
56
57    #[error("remote connection failed: {0}")]
58    RemoteConnection(String),
59
60    #[error("remote config missing or invalid")]
61    RemoteConfigError,
62
63    #[error("invalid tree entry name: {0}")]
64    InvalidEntryName(String),
65
66    #[error("duplicate tree entry name: {0}")]
67    DuplicateEntryName(String),
68
69    #[error("hardlink target not found: {0}")]
70    HardlinkTargetNotFound(String),
71
72    #[error("cannot create device node without privileges: {0}")]
73    DeviceNodePermission(PathBuf),
74
75    #[error("io error at {path}: {source}")]
76    Io {
77        path: PathBuf,
78        #[source]
79        source: std::io::Error,
80    },
81
82    #[error("cbor serialization error: {0}")]
83    CborEncode(#[from] ciborium::ser::Error<std::io::Error>),
84
85    #[error("cbor deserialization error: {0}")]
86    CborDecode(#[from] ciborium::de::Error<std::io::Error>),
87
88    #[error("config error: {0}")]
89    Config(#[from] toml::de::Error),
90
91    #[error("config serialization error: {0}")]
92    ConfigSerialize(#[from] toml::ser::Error),
93
94    #[error("invalid hash hex: {0}")]
95    InvalidHashHex(String),
96
97    #[error("xattr error on {path}: {message}")]
98    Xattr { path: PathBuf, message: String },
99
100    #[error("transport error: {message}")]
101    Transport { message: String },
102
103    #[error("invalid conflict resolution strategy: {0}")]
104    InvalidConflictResolution(String),
105
106    #[error("corrupt object: {0}")]
107    CorruptObjectMessage(String),
108
109    #[error("invalid object type: {0}")]
110    InvalidObjectType(String),
111
112    #[error("metadata key not found: {0}")]
113    MetadataKeyNotFound(String),
114}
115
116pub type Result<T> = std::result::Result<T, Error>;
117
118/// helper to wrap io errors with path context
119pub trait IoResultExt<T> {
120    fn with_path(self, path: impl Into<PathBuf>) -> Result<T>;
121}
122
123impl<T> IoResultExt<T> for std::io::Result<T> {
124    fn with_path(self, path: impl Into<PathBuf>) -> Result<T> {
125        self.map_err(|source| Error::Io {
126            path: path.into(),
127            source,
128        })
129    }
130}