1use std::path::PathBuf;
2
3use crate::Hash;
4
5#[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
118pub 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}