1use crate::{PackageId, graph::feature::FeatureId};
7use Error::*;
8use camino::Utf8PathBuf;
9use std::{error, fmt};
10pub use target_spec::Error as TargetSpecError;
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")]
66 InvalidFeaturesOnlySummary {
67 unknown_summary_ids: Vec<crate::graph::summaries::SummaryId>,
69
70 unknown_features: Vec<crate::graph::summaries::UnknownFeatures>,
73
74 empty_entries: Vec<crate::graph::summaries::SummaryId>,
79 },
80 #[cfg(feature = "summaries")]
87 InvalidPlatformSpecSummary {
88 build_platform: crate::graph::cargo::BuildPlatform,
90
91 error: crate::platform::PlatformSpecSummaryError,
93 },
94 #[cfg(feature = "summaries")]
97 UnknownRegistryName {
98 message: String,
100
101 summary: Box<crate::graph::summaries::ThirdPartySummary>,
103
104 registry_name: String,
106 },
107 #[cfg(feature = "summaries")]
109 TomlSerializeError(toml::ser::Error),
110}
111
112impl Error {
113 pub(crate) fn command_error(err: cargo_metadata::Error) -> Self {
114 Error::CommandError(Box::new(err))
115 }
116
117 pub(crate) fn unknown_feature_id(feature_id: FeatureId<'_>) -> Self {
118 Error::UnknownFeatureId(
119 feature_id.package_id().clone(),
120 feature_id.label().to_string(),
121 )
122 }
123}
124
125impl fmt::Display for Error {
126 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127 match self {
128 CommandError(_) => write!(f, "`cargo metadata` execution failed"),
129 MetadataParseError(_) => write!(f, "`cargo metadata` returned invalid JSON output"),
130 MetadataSerializeError(_) => write!(f, "failed to serialize `cargo metadata` to JSON"),
131 PackageGraphConstructError(s) => write!(f, "failed to construct package graph: {s}"),
132 UnknownPackageId(id) => write!(f, "unknown package ID: {id}"),
133 UnknownFeatureId(package_id, feature) => {
134 write!(f, "unknown feature ID: '{package_id}/{feature}'")
135 }
136 UnknownWorkspacePath(path) => write!(f, "unknown workspace path: {path}"),
137 UnknownWorkspaceName(name) => write!(f, "unknown workspace package name: {name}"),
138 TargetSpecError(msg, _) => write!(f, "target spec error while {msg}"),
139 PackageGraphInternalError(msg) => write!(f, "internal error in package graph: {msg}"),
140 FeatureGraphInternalError(msg) => write!(f, "internal error in feature graph: {msg}"),
141 #[cfg(feature = "summaries")]
142 UnknownSummaryId(summary_id) => write!(f, "unknown summary ID: {summary_id}"),
143 #[cfg(feature = "summaries")]
144 UnknownPackageSetSummary {
145 message,
146 unknown_summary_ids,
147 unknown_workspace_members,
148 unknown_third_party,
149 } => {
150 writeln!(f, "unknown elements: {message}")?;
151 if !unknown_summary_ids.is_empty() {
152 writeln!(f, "* unknown summary IDs:")?;
153 for summary_id in unknown_summary_ids {
154 writeln!(f, " - {summary_id}")?;
155 }
156 }
157 if !unknown_workspace_members.is_empty() {
158 writeln!(f, "* unknown workspace names:")?;
159 for workspace_member in unknown_workspace_members {
160 writeln!(f, " - {workspace_member}")?;
161 }
162 }
163 if !unknown_third_party.is_empty() {
164 writeln!(f, "* unknown third-party:")?;
165 for third_party in unknown_third_party {
166 writeln!(f, " - {third_party}")?;
167 }
168 }
169 Ok(())
170 }
171 #[cfg(feature = "summaries")]
172 InvalidFeaturesOnlySummary {
173 unknown_summary_ids,
174 unknown_features,
175 empty_entries,
176 } => {
177 writeln!(f, "invalid entries: resolving features-only")?;
178 if !unknown_summary_ids.is_empty() {
179 writeln!(f, "* unknown summary IDs:")?;
180 for summary_id in unknown_summary_ids {
181 writeln!(f, " - {summary_id}")?;
182 }
183 }
184 if !unknown_features.is_empty() {
185 writeln!(f, "* unknown features:")?;
186 for entry in unknown_features {
187 writeln!(f, " - {}:", entry.summary_id)?;
188 if !entry.features.is_empty() {
189 writeln!(f, " - features: {}", join_names(&entry.features))?;
190 }
191 if !entry.optional_deps.is_empty() {
192 writeln!(
193 f,
194 " - optional-deps: {}",
195 join_names(&entry.optional_deps)
196 )?;
197 }
198 }
199 }
200 if !empty_entries.is_empty() {
201 writeln!(
202 f,
203 "* entries that enable nothing (base = false, no features):"
204 )?;
205 for summary_id in empty_entries {
206 writeln!(f, " - {summary_id}")?;
207 }
208 }
209 Ok(())
210 }
211 #[cfg(feature = "summaries")]
212 InvalidPlatformSpecSummary {
213 build_platform,
214 error,
215 } => {
216 let which = match build_platform {
217 crate::graph::cargo::BuildPlatform::Host => "host",
218 crate::graph::cargo::BuildPlatform::Target => "target",
219 };
220 write!(f, "invalid {which} platform `{}`", error.triple())?;
221 error.fmt_position(f)?;
222 write!(f, " in summary")
223 }
224 #[cfg(feature = "summaries")]
225 UnknownRegistryName {
226 message,
227 summary,
228 registry_name,
229 } => {
230 writeln!(
231 f,
232 "unknown registry name: {message}\n* for third-party: {summary}\n* name: {registry_name}\n"
233 )
234 }
235 #[cfg(feature = "summaries")]
236 TomlSerializeError(_) => write!(f, "failed to serialize to TOML"),
237 }
238 }
239}
240
241impl error::Error for Error {
242 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
243 match self {
244 MetadataParseError(err) => Some(err),
245 MetadataSerializeError(err) => Some(err),
246 CommandError(err) => Some(err.as_ref()),
247 PackageGraphConstructError(_) => None,
248 UnknownPackageId(_) => None,
249 UnknownFeatureId(_, _) => None,
250 UnknownWorkspacePath(_) => None,
251 UnknownWorkspaceName(_) => None,
252 TargetSpecError(_, err) => Some(err),
253 PackageGraphInternalError(_) => None,
254 FeatureGraphInternalError(_) => None,
255 #[cfg(feature = "summaries")]
256 UnknownSummaryId(_) => None,
257 #[cfg(feature = "summaries")]
258 UnknownPackageSetSummary { .. } => None,
259 #[cfg(feature = "summaries")]
260 InvalidFeaturesOnlySummary { .. } => None,
261 #[cfg(feature = "summaries")]
262 InvalidPlatformSpecSummary { error, .. } => Some(error),
263 #[cfg(feature = "summaries")]
264 UnknownRegistryName { .. } => None,
265 #[cfg(feature = "summaries")]
266 TomlSerializeError(err) => Some(err),
267 }
268 }
269}
270
271#[cfg(feature = "summaries")]
272fn join_names(names: &std::collections::BTreeSet<String>) -> String {
273 names
274 .iter()
275 .map(String::as_str)
276 .collect::<Vec<_>>()
277 .join(", ")
278}
279
280#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
282#[non_exhaustive]
283pub enum FeatureGraphWarning {
284 MissingFeature {
286 stage: FeatureBuildStage,
288 package_id: PackageId,
290 feature_name: String,
292 },
293
294 SelfLoop {
301 package_id: PackageId,
303 feature_name: String,
305 },
306}
307
308impl fmt::Display for FeatureGraphWarning {
309 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
310 use FeatureGraphWarning::*;
311 match self {
312 MissingFeature {
313 stage,
314 package_id,
315 feature_name,
316 } => write!(
317 f,
318 "{stage}: for package '{package_id}', missing feature '{feature_name}'"
319 ),
320 SelfLoop {
321 package_id,
322 feature_name,
323 } => write!(
324 f,
325 "for package '{package_id}', self-loop detected for named feature '{feature_name}'"
326 ),
327 }
328 }
329}
330
331#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
333#[non_exhaustive]
334pub enum FeatureBuildStage {
335 AddNamedFeatureEdges {
337 package_id: PackageId,
339 from_feature: String,
341 },
342 AddDependencyEdges {
344 package_id: PackageId,
346 dep_name: String,
348 },
349}
350
351impl fmt::Display for FeatureBuildStage {
352 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
353 use FeatureBuildStage::*;
354 match self {
355 AddNamedFeatureEdges {
356 package_id,
357 from_feature,
358 } => write!(
359 f,
360 "for package '{package_id}', while adding named feature edges from '{from_feature}'"
361 ),
362 AddDependencyEdges {
363 package_id,
364 dep_name,
365 } => write!(
366 f,
367 "for package '{package_id}', while adding edges for dependency '{dep_name}'",
368 ),
369 }
370 }
371}