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 {
194 package_id: PackageId,
196 feature_name: String,
198 },
199}
200
201impl fmt::Display for FeatureGraphWarning {
202 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
203 use FeatureGraphWarning::*;
204 match self {
205 MissingFeature {
206 stage,
207 package_id,
208 feature_name,
209 } => write!(
210 f,
211 "{stage}: for package '{package_id}', missing feature '{feature_name}'"
212 ),
213 SelfLoop {
214 package_id,
215 feature_name,
216 } => write!(
217 f,
218 "for package '{package_id}', self-loop detected for named feature '{feature_name}'"
219 ),
220 }
221 }
222}
223
224#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
226#[non_exhaustive]
227pub enum FeatureBuildStage {
228 AddNamedFeatureEdges {
230 package_id: PackageId,
232 from_feature: String,
234 },
235 AddDependencyEdges {
237 package_id: PackageId,
239 dep_name: String,
241 },
242}
243
244impl fmt::Display for FeatureBuildStage {
245 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
246 use FeatureBuildStage::*;
247 match self {
248 AddNamedFeatureEdges {
249 package_id,
250 from_feature,
251 } => write!(
252 f,
253 "for package '{package_id}', while adding named feature edges from '{from_feature}'"
254 ),
255 AddDependencyEdges {
256 package_id,
257 dep_name,
258 } => write!(
259 f,
260 "for package '{package_id}', while adding edges for dependency '{dep_name}'",
261 ),
262 }
263 }
264}