use crate::{graph::feature::FeatureId, PackageId};
use camino::Utf8PathBuf;
use std::{error, fmt};
pub use target_spec::Error as TargetSpecError;
use Error::*;
#[derive(Debug)]
#[non_exhaustive]
pub enum Error {
CommandError(Box<dyn error::Error + Send + Sync>),
MetadataParseError(serde_json::Error),
MetadataSerializeError(serde_json::Error),
PackageGraphConstructError(String),
UnknownPackageId(PackageId),
UnknownFeatureId(PackageId, String),
UnknownWorkspacePath(Utf8PathBuf),
UnknownWorkspaceName(String),
TargetSpecError(String, TargetSpecError),
PackageGraphInternalError(String),
FeatureGraphInternalError(String),
#[cfg(feature = "summaries")]
UnknownSummaryId(guppy_summaries::SummaryId),
#[cfg(feature = "summaries")]
UnknownPackageSetSummary {
message: String,
unknown_summary_ids: Vec<crate::graph::summaries::SummaryId>,
unknown_workspace_members: Vec<String>,
unknown_third_party: Vec<crate::graph::summaries::ThirdPartySummary>,
},
#[cfg(feature = "summaries")]
UnknownRegistryName {
message: String,
summary: Box<crate::graph::summaries::ThirdPartySummary>,
registry_name: String,
},
#[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),
}
}
}
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[non_exhaustive]
pub enum FeatureGraphWarning {
MissingFeature {
stage: FeatureBuildStage,
package_id: PackageId,
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
),
}
}
}
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[non_exhaustive]
pub enum FeatureBuildStage {
AddNamedFeatureEdges {
package_id: PackageId,
from_feature: String,
},
AddDependencyEdges {
package_id: PackageId,
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,
),
}
}
}