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")]
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: {message}\n* for third-party: {summary}\n* name: {registry_name}\n"
144 )
145 }
146 #[cfg(feature = "summaries")]
147 TomlSerializeError(_) => write!(f, "failed to serialize to TOML"),
148 }
149 }
150}
151
152impl error::Error for Error {
153 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
154 match self {
155 MetadataParseError(err) => Some(err),
156 MetadataSerializeError(err) => Some(err),
157 CommandError(err) => Some(err.as_ref()),
158 PackageGraphConstructError(_) => None,
159 UnknownPackageId(_) => None,
160 UnknownFeatureId(_, _) => None,
161 UnknownWorkspacePath(_) => None,
162 UnknownWorkspaceName(_) => None,
163 TargetSpecError(_, err) => Some(err),
164 PackageGraphInternalError(_) => None,
165 FeatureGraphInternalError(_) => None,
166 #[cfg(feature = "summaries")]
167 UnknownSummaryId(_) => None,
168 #[cfg(feature = "summaries")]
169 UnknownPackageSetSummary { .. } => None,
170 #[cfg(feature = "summaries")]
171 UnknownRegistryName { .. } => None,
172 #[cfg(feature = "summaries")]
173 TomlSerializeError(err) => Some(err),
174 }
175 }
176}
177
178#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
180#[non_exhaustive]
181pub enum FeatureGraphWarning {
182 MissingFeature {
184 stage: FeatureBuildStage,
186 package_id: PackageId,
188 feature_name: String,
190 },
191
192 SelfLoop {
199 package_id: PackageId,
201 feature_name: String,
203 },
204}
205
206impl fmt::Display for FeatureGraphWarning {
207 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
208 use FeatureGraphWarning::*;
209 match self {
210 MissingFeature {
211 stage,
212 package_id,
213 feature_name,
214 } => write!(
215 f,
216 "{stage}: for package '{package_id}', missing feature '{feature_name}'"
217 ),
218 SelfLoop {
219 package_id,
220 feature_name,
221 } => write!(
222 f,
223 "for package '{package_id}', self-loop detected for named feature '{feature_name}'"
224 ),
225 }
226 }
227}
228
229#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
231#[non_exhaustive]
232pub enum FeatureBuildStage {
233 AddNamedFeatureEdges {
235 package_id: PackageId,
237 from_feature: String,
239 },
240 AddDependencyEdges {
242 package_id: PackageId,
244 dep_name: String,
246 },
247}
248
249impl fmt::Display for FeatureBuildStage {
250 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251 use FeatureBuildStage::*;
252 match self {
253 AddNamedFeatureEdges {
254 package_id,
255 from_feature,
256 } => write!(
257 f,
258 "for package '{package_id}', while adding named feature edges from '{from_feature}'"
259 ),
260 AddDependencyEdges {
261 package_id,
262 dep_name,
263 } => write!(
264 f,
265 "for package '{package_id}', while adding edges for dependency '{dep_name}'",
266 ),
267 }
268 }
269}