1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
// Copyright (c) The cargo-guppy Contributors
// SPDX-License-Identifier: MIT OR Apache-2.0
//! Contains types that describe errors and warnings that `guppy` methods can return.
use crate::{graph::feature::FeatureId, PackageId};
use camino::Utf8PathBuf;
use std::{error, fmt};
pub use target_spec::Error as TargetSpecError;
use Error::*;
/// Error type describing the sorts of errors `guppy` can return.
#[derive(Debug)]
#[non_exhaustive]
pub enum Error {
/// An error occurred while executing `cargo metadata`.
CommandError(Box<dyn error::Error + Send + Sync>),
/// An error occurred while parsing `cargo metadata` JSON.
MetadataParseError(serde_json::Error),
/// An error occurred while serializing `cargo metadata` JSON.
MetadataSerializeError(serde_json::Error),
/// An error occurred while constructing a `PackageGraph` from parsed metadata.
PackageGraphConstructError(String),
/// A package ID was unknown to this `PackageGraph`.
UnknownPackageId(PackageId),
/// A feature ID was unknown to this `FeatureGraph`.
UnknownFeatureId(PackageId, String),
/// A package specified by path was unknown to this workspace.
UnknownWorkspacePath(Utf8PathBuf),
/// A package specified by name was unknown to this workspace.
UnknownWorkspaceName(String),
/// An error was returned by `target-spec`.
TargetSpecError(String, TargetSpecError),
/// An internal error occurred within this `PackageGraph`.
PackageGraphInternalError(String),
/// An internal error occurred within this `FeatureGraph`.
FeatureGraphInternalError(String),
/// A summary ID was unknown to this `PackageGraph`.
///
/// This is present if the `summaries` feature is enabled.
#[cfg(feature = "summaries")]
UnknownSummaryId(guppy_summaries::SummaryId),
/// While resolving a [`PackageSetSummary`](crate::graph::summaries::PackageSetSummary),
/// some elements were unknown to the `PackageGraph`.
///
/// This is present if the `summaries` feature is enabled.
#[cfg(feature = "summaries")]
UnknownPackageSetSummary {
/// A description attached to the error.
message: String,
/// Summary IDs that weren't known to the `PackageGraph`.
unknown_summary_ids: Vec<crate::graph::summaries::SummaryId>,
/// Workspace packages that weren't known to the `PackageGraph`.
unknown_workspace_members: Vec<String>,
/// Third-party packages that weren't known to the `PackageGraph`.
unknown_third_party: Vec<crate::graph::summaries::ThirdPartySummary>,
},
/// While resolving a [`PackageSetSummary`](crate::graph::summaries::PackageSetSummary),
/// an unknown external registry was encountered.
#[cfg(feature = "summaries")]
UnknownRegistryName {
/// A description attached to the error.
message: String,
/// The summary for which the name wasn't recognized.
summary: Box<crate::graph::summaries::ThirdPartySummary>,
/// The registry name that wasn't recognized.
registry_name: String,
},
/// An error occurred while serializing to TOML.
#[cfg(feature = "summaries")]
TomlSerializeError(toml::ser::Error),
}
impl Error {
pub(crate) fn command_error(err: cargo_metadata::Error) -> Self {
Error::CommandError(Box::new(err))
}
pub(crate) fn unknown_feature_id(feature_id: FeatureId<'_>) -> Self {
Error::UnknownFeatureId(
feature_id.package_id().clone(),
feature_id.label().to_string(),
)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CommandError(_) => write!(f, "`cargo metadata` execution failed"),
MetadataParseError(_) => write!(f, "`cargo metadata` returned invalid JSON output"),
MetadataSerializeError(_) => write!(f, "failed to serialize `cargo metadata` to JSON"),
PackageGraphConstructError(s) => write!(f, "failed to construct package graph: {}", s),
UnknownPackageId(id) => write!(f, "unknown package ID: {}", id),
UnknownFeatureId(package_id, feature) => {
write!(f, "unknown feature ID: '{}/{}'", package_id, feature)
}
UnknownWorkspacePath(path) => write!(f, "unknown workspace path: {}", path),
UnknownWorkspaceName(name) => write!(f, "unknown workspace package name: {}", name),
TargetSpecError(msg, _) => write!(f, "target spec error while {}", msg),
PackageGraphInternalError(msg) => write!(f, "internal error in package graph: {}", msg),
FeatureGraphInternalError(msg) => write!(f, "internal error in feature graph: {}", msg),
#[cfg(feature = "summaries")]
UnknownSummaryId(summary_id) => write!(f, "unknown summary ID: {}", summary_id),
#[cfg(feature = "summaries")]
UnknownPackageSetSummary {
message,
unknown_summary_ids,
unknown_workspace_members,
unknown_third_party,
} => {
writeln!(f, "unknown elements: {}", message)?;
if !unknown_summary_ids.is_empty() {
writeln!(f, "* unknown summary IDs:")?;
for summary_id in unknown_summary_ids {
writeln!(f, " - {}", summary_id)?;
}
}
if !unknown_workspace_members.is_empty() {
writeln!(f, "* unknown workspace names:")?;
for workspace_member in unknown_workspace_members {
writeln!(f, " - {}", workspace_member)?;
}
}
if !unknown_third_party.is_empty() {
writeln!(f, "* unknown third-party:")?;
for third_party in unknown_third_party {
writeln!(f, " - {}", third_party)?;
}
}
Ok(())
}
#[cfg(feature = "summaries")]
UnknownRegistryName {
message,
summary,
registry_name,
} => {
writeln!(
f,
"unknown registry name: {}\n* for third-party: {}\n* name: {}\n",
message, summary, registry_name
)
}
#[cfg(feature = "summaries")]
TomlSerializeError(_) => write!(f, "failed to serialize to TOML"),
}
}
}
impl error::Error for Error {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
MetadataParseError(err) => Some(err),
MetadataSerializeError(err) => Some(err),
CommandError(err) => Some(err.as_ref()),
PackageGraphConstructError(_) => None,
UnknownPackageId(_) => None,
UnknownFeatureId(_, _) => None,
UnknownWorkspacePath(_) => None,
UnknownWorkspaceName(_) => None,
TargetSpecError(_, err) => Some(err),
PackageGraphInternalError(_) => None,
FeatureGraphInternalError(_) => None,
#[cfg(feature = "summaries")]
UnknownSummaryId(_) => None,
#[cfg(feature = "summaries")]
UnknownPackageSetSummary { .. } => None,
#[cfg(feature = "summaries")]
UnknownRegistryName { .. } => None,
#[cfg(feature = "summaries")]
TomlSerializeError(err) => Some(err),
}
}
}
/// Describes warnings emitted during feature graph construction.
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[non_exhaustive]
pub enum FeatureGraphWarning {
/// A feature that was requested is missing from a package.
MissingFeature {
/// The stage of building the feature graph where the warning occurred.
stage: FeatureBuildStage,
/// The package ID for which the feature was requested.
package_id: PackageId,
/// The name of the feature.
feature_name: String,
},
/// A self-loop was discovered.
SelfLoop {
/// The package ID for which the self-loop was discovered.
package_id: PackageId,
/// The name of the feature for which the self-loop was discovered.
feature_name: String,
},
}
impl fmt::Display for FeatureGraphWarning {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use FeatureGraphWarning::*;
match self {
MissingFeature {
stage,
package_id,
feature_name,
} => write!(
f,
"{}: for package '{}', missing feature '{}'",
stage, package_id, feature_name
),
SelfLoop {
package_id,
feature_name,
} => write!(
f,
"for package '{}', self-loop detected for named feature '{}'",
package_id, feature_name
),
}
}
}
/// Describes the stage of construction at which a feature graph warning occurred.
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[non_exhaustive]
pub enum FeatureBuildStage {
/// The warning occurred while adding edges for the `[features]` section of `Cargo.toml`.
AddNamedFeatureEdges {
/// The package ID for which edges were being added.
package_id: PackageId,
/// The feature name from which edges were being added.
from_feature: String,
},
/// The warning occurred while adding dependency edges.
AddDependencyEdges {
/// The package ID for which edges were being added.
package_id: PackageId,
/// The name of the dependency.
dep_name: String,
},
}
impl fmt::Display for FeatureBuildStage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use FeatureBuildStage::*;
match self {
AddNamedFeatureEdges {
package_id,
from_feature,
} => write!(
f,
"for package '{}', while adding named feature edges from '{}'",
package_id, from_feature
),
AddDependencyEdges {
package_id,
dep_name,
} => write!(
f,
"for package '{}', while adding edges for dependency '{}'",
package_id, dep_name,
),
}
}
}