1use std::error::Error as StdError;
2use std::fmt;
3use std::io;
4use std::path::PathBuf;
5
6use crate::CheckResult;
7
8pub type Result<T> = std::result::Result<T, Error>;
10
11#[derive(Debug)]
13pub enum Error {
14 InvalidRustLibName(String),
15 InvalidRustLibPath {
16 path: String,
17 reason: &'static str,
18 },
19 RustLibAlreadyExists(String),
20 RustLibNotFound(String),
21 RustLibIsNotDirectory(String),
22 DuplicateWritePath(String),
23 NonUtf8Path(PathBuf),
24 NonUtf8File(PathBuf),
25 SymlinkNotAllowed(PathBuf),
26 UnsupportedFileType(PathBuf),
27 RootsOverlap {
28 rust_libs_root: PathBuf,
29 work_root: PathBuf,
30 },
31 MissingRequiredFile(&'static str),
32 InvalidVersion(String),
33 InvalidCargoManifest(String),
34 VersionMismatch {
35 version_file: String,
36 cargo_manifest: String,
37 },
38 InvalidRegistryToken,
39 CheckFailed(CheckResult),
40 Io {
41 action: &'static str,
42 path: PathBuf,
43 source: io::Error,
44 },
45 Sandbox {
46 stage: String,
47 message: String,
48 },
49 Publish(String),
50}
51
52impl Error {
53 pub(crate) fn io(action: &'static str, path: impl Into<PathBuf>, source: io::Error) -> Self {
54 Self::Io {
55 action,
56 path: path.into(),
57 source,
58 }
59 }
60}
61
62impl fmt::Display for Error {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 match self {
65 Self::InvalidRustLibName(name) => write!(
66 f,
67 "invalid Rust library name {name:?}; use ASCII letters, digits, '-' or '_'"
68 ),
69 Self::InvalidRustLibPath { path, reason } => {
70 write!(f, "invalid Rust library path {path:?}: {reason}")
71 }
72 Self::RustLibAlreadyExists(name) => {
73 write!(f, "Rust library {name:?} already exists")
74 }
75 Self::RustLibNotFound(name) => write!(f, "Rust library {name:?} was not found"),
76 Self::RustLibIsNotDirectory(name) => {
77 write!(f, "Rust library {name:?} is not a directory")
78 }
79 Self::DuplicateWritePath(path) => {
80 write!(f, "write batch contains duplicate path {path:?}")
81 }
82 Self::NonUtf8Path(path) => {
83 write!(
84 f,
85 "Rust library contains a non-UTF-8 path: {}",
86 path.display()
87 )
88 }
89 Self::NonUtf8File(path) => {
90 write!(f, "Rust library file is not UTF-8: {}", path.display())
91 }
92 Self::SymlinkNotAllowed(path) => {
93 write!(
94 f,
95 "Rust library symlinks are not allowed: {}",
96 path.display()
97 )
98 }
99 Self::UnsupportedFileType(path) => write!(
100 f,
101 "Rust library entry is not a regular file or directory: {}",
102 path.display()
103 ),
104 Self::RootsOverlap {
105 rust_libs_root,
106 work_root,
107 } => write!(
108 f,
109 "Rust libraries root ({}) and work root ({}) must not overlap",
110 rust_libs_root.display(),
111 work_root.display()
112 ),
113 Self::MissingRequiredFile(path) => {
114 write!(f, "Rust library is missing required file {path}")
115 }
116 Self::InvalidVersion(value) => write!(
117 f,
118 "invalid Cargo.toml [package].version {value:?}; expected canonical major.minor.patch"
119 ),
120 Self::InvalidCargoManifest(message) => {
121 write!(f, "invalid Cargo.toml: {message}")
122 }
123 Self::VersionMismatch {
124 version_file,
125 cargo_manifest,
126 } => write!(
127 f,
128 "version {version_file} does not match Cargo.toml package version {cargo_manifest}"
129 ),
130 Self::InvalidRegistryToken => f.write_str("crates.io registry token is empty"),
131 Self::CheckFailed(result) => {
132 if let Some(stage) = result.failure() {
133 write!(
134 f,
135 "Rust library cannot be published because its {} check failed",
136 stage.stage
137 )
138 } else {
139 f.write_str(
140 "Rust library cannot be published because its full check did not pass",
141 )
142 }
143 }
144 Self::Io {
145 action,
146 path,
147 source,
148 } => write!(f, "failed to {action} {}: {source}", path.display()),
149 Self::Sandbox { stage, message } => {
150 write!(f, "Podman failed during {stage}: {message}")
151 }
152 Self::Publish(message) => write!(f, "crates.io publication failed: {message}"),
153 }
154 }
155}
156
157impl StdError for Error {
158 fn source(&self) -> Option<&(dyn StdError + 'static)> {
159 match self {
160 Self::Io { source, .. } => Some(source),
161 _ => None,
162 }
163 }
164}