1use crate::{graph::feature::FeatureId, PackageId};
7use camino::Utf8PathBuf;
8use std::{error, fmt};
9pub use target_spec::Error as TargetSpecError;
10use Error::*;
11
12#[derive(Debug)]
14#[non_exhaustive]
15pub enum Error {
16 CommandError(Box<dyn error::Error + Send + Sync>),
18 MetadataParseError(serde_json::Error),
20 MetadataSerializeError(serde_json::Error),
22 PackageGraphConstructError(String),
24 UnknownPackageId(PackageId),
26 UnknownFeatureId(PackageId, String),
28 UnknownWorkspacePath(Utf8PathBuf),
30 UnknownWorkspaceName(String),
32 TargetSpecError(String, TargetSpecError),
34 PackageGraphInternalError(String),
36 FeatureGraphInternalError(String),
38 #[cfg(feature = "summaries")]
42 UnknownSummaryId(guppy_summaries::SummaryId),
43 #[cfg(feature = "summaries")]
48 UnknownPackageSetSummary {
49 message: String,
51 unknown_summary_ids: Vec<crate::graph::summaries::SummaryId>,
53 unknown_workspace_members: Vec<String>,
55 unknown_third_party: Vec<crate::graph::summaries::ThirdPartySummary>,
57 },
58 #[cfg(feature = "summaries")]
61 UnknownRegistryName {
62 message: String,
64
65 summary: Box<crate::graph::summaries::ThirdPartySummary>,
67
68 registry_name: String,
70 },
71 #[cfg(feature = "summaries")]
73 TomlSerializeError(toml::ser::Error),
74}
75
76impl Error {
77 pub(crate) fn command_error(err: cargo_metadata::Error) -> Self {
78 Error::CommandError(Box::new(err))
79 }
80
81 pub(crate) fn unknown_feature_id(feature_id: FeatureId<'_>) -> Self {
82 Error::UnknownFeatureId(
83 feature_id.package_id().clone(),
84 feature_id.label().to_string(),
85 )
86 }
87}
88
89impl fmt::Display for Error {
90 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91 match self {
92 CommandError(_) => write!(f, "`cargo metadata` execution failed"),
93 MetadataParseError(_) => write!(f, "`cargo metadata` returned invalid JSON output"),
94 MetadataSerializeError(_) => write!(f, "failed to serialize `cargo metadata` to JSON"),
95 PackageGraphConstructError(s) => write!(f, "failed to construct package graph: {}", s),
96 UnknownPackageId(id) => write!(f, "unknown package ID: {}", id),
97 UnknownFeatureId(package_id, feature) => {
98 write!(f, "unknown feature ID: '{}/{}'", package_id, feature)
99 }
100 UnknownWorkspacePath(path) => write!(f, "unknown workspace path: {}", path),
101 UnknownWorkspaceName(name) => write!(f, "unknown workspace package name: {}", name),
102 TargetSpecError(msg, _) => write!(f, "target spec error while {}", msg),
103 PackageGraphInternalError(msg) => write!(f, "internal error in package graph: {}", msg),
104 FeatureGraphInternalError(msg) => write!(f, "internal error in feature graph: {}", msg),
105 #[cfg(feature = "summaries")]
106 UnknownSummaryId(summary_id) => write!(f, "unknown summary ID: {}", summary_id),
107 #[cfg(feature = "summaries")]
108 UnknownPackageSetSummary {
109 message,
110 unknown_summary_ids,
111 unknown_workspace_members,
112 unknown_third_party,
113 } => {
114 writeln!(f, "unknown elements: {}", message)?;
115 if !unknown_summary_ids.is_empty() {
116 writeln!(f, "* unknown summary IDs:")?;
117 for summary_id in unknown_summary_ids {
118 writeln!(f, " - {}", summary_id)?;
119 }
120 }
121 if !unknown_workspace_members.is_empty() {
122 writeln!(f, "* unknown workspace names:")?;
123 for workspace_member in unknown_workspace_members {
124 writeln!(f, " - {}", workspace_member)?;
125 }
126 }
127 if !unknown_third_party.is_empty() {
128 writeln!(f, "* unknown third-party:")?;
129 for third_party in unknown_third_party {
130 writeln!(f, " - {}", third_party)?;
131 }
132 }
133 Ok(())
134 }
135 #[cfg(feature = "summaries")]
136 UnknownRegistryName {
137 message,
138 summary,
139 registry_name,
140 } => {
141 writeln!(
142 f,
143 "unknown registry name: {}\n* for third-party: {}\n* name: {}\n",
144 message, summary, registry_name
145 )
146 }
147 #[cfg(feature = "summaries")]
148 TomlSerializeError(_) => write!(f, "failed to serialize to TOML"),
149 }
150 }
151}
152
153impl error::Error for Error {
154 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
155 match self {
156 MetadataParseError(err) => Some(err),
157 MetadataSerializeError(err) => Some(err),
158 CommandError(err) => Some(err.as_ref()),
159 PackageGraphConstructError(_) => None,
160 UnknownPackageId(_) => None,
161 UnknownFeatureId(_, _) => None,
162 UnknownWorkspacePath(_) => None,
163 UnknownWorkspaceName(_) => None,
164 TargetSpecError(_, err) => Some(err),
165 PackageGraphInternalError(_) => None,
166 FeatureGraphInternalError(_) => None,
167 #[cfg(feature = "summaries")]
168 UnknownSummaryId(_) => None,
169 #[cfg(feature = "summaries")]
170 UnknownPackageSetSummary { .. } => None,
171 #[cfg(feature = "summaries")]
172 UnknownRegistryName { .. } => None,
173 #[cfg(feature = "summaries")]
174 TomlSerializeError(err) => Some(err),
175 }
176 }
177}
178
179#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
181#[non_exhaustive]
182pub enum FeatureGraphWarning {
183 MissingFeature {
185 stage: FeatureBuildStage,
187 package_id: PackageId,
189 feature_name: String,
191 },
192
193 SelfLoop {
195 package_id: PackageId,
197 feature_name: String,
199 },
200}
201
202impl fmt::Display for FeatureGraphWarning {
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 use FeatureGraphWarning::*;
205 match self {
206 MissingFeature {
207 stage,
208 package_id,
209 feature_name,
210 } => write!(
211 f,
212 "{}: for package '{}', missing feature '{}'",
213 stage, package_id, feature_name
214 ),
215 SelfLoop {
216 package_id,
217 feature_name,
218 } => write!(
219 f,
220 "for package '{}', self-loop detected for named feature '{}'",
221 package_id, feature_name
222 ),
223 }
224 }
225}
226
227#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
229#[non_exhaustive]
230pub enum FeatureBuildStage {
231 AddNamedFeatureEdges {
233 package_id: PackageId,
235 from_feature: String,
237 },
238 AddDependencyEdges {
240 package_id: PackageId,
242 dep_name: String,
244 },
245}
246
247impl fmt::Display for FeatureBuildStage {
248 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
249 use FeatureBuildStage::*;
250 match self {
251 AddNamedFeatureEdges {
252 package_id,
253 from_feature,
254 } => write!(
255 f,
256 "for package '{}', while adding named feature edges from '{}'",
257 package_id, from_feature
258 ),
259 AddDependencyEdges {
260 package_id,
261 dep_name,
262 } => write!(
263 f,
264 "for package '{}', while adding edges for dependency '{}'",
265 package_id, dep_name,
266 ),
267 }
268 }
269}