use std::path::PathBuf;
use callisto_model::{GroupName, ManifestError, PackageId, TagTemplateError, VersionParseError};
pub use crate::locate::LocateError;
#[derive(Clone, Debug, thiserror::Error, miette::Diagnostic, PartialEq, Eq)]
#[allow(clippy::result_large_err)]
#[non_exhaustive]
pub enum GraphError {
#[error(transparent)]
#[diagnostic(transparent)]
Locate(#[from] LocateError),
#[error(transparent)]
#[diagnostic(transparent)]
Manifest(#[from] ManifestError),
#[error(transparent)]
#[diagnostic(transparent)]
Config(#[from] ConfigError),
#[error(transparent)]
#[diagnostic(transparent)]
Format(#[from] callisto_format::ParseError),
#[error("parsing changeset {}: {source}", .path.display())]
ParseChangeset {
path: PathBuf,
source: callisto_format::ParseError,
},
#[error(transparent)]
#[diagnostic(transparent)]
Bump(#[from] callisto_format::BumpError),
#[error(transparent)]
#[diagnostic(transparent)]
Changelog(#[from] callisto_changelog::ChangelogError),
#[cfg(feature = "inference")]
#[error(transparent)]
Conventional(#[from] callisto_conventional::ConventionalError),
#[error(transparent)]
TagTemplate(#[from] callisto_model::TagTemplateError),
#[error(transparent)]
VersionParse(#[from] callisto_model::VersionParseError),
#[error(transparent)]
#[diagnostic(transparent)]
Model(#[from] callisto_model::ModelError),
#[error("vcs error: {0}")]
#[diagnostic(transparent)]
Vcs(#[from] callisto_vcs::VcsError),
#[error("command error: {0}")]
Command(#[from] callisto_model::CommandError),
#[error("package `{id}` is defined at multiple paths: {}", .paths.iter().map(|p| p.display().to_string()).collect::<Vec<_>>().join(", "))]
#[diagnostic(
code(E100),
help("Ensure package IDs are unique across workspace manifest paths.")
)]
DuplicatePackage { id: PackageId, paths: Vec<PathBuf> },
#[error("package at `{path}` declares conflicting identities: {}", .ids.iter().map(|i| i.display_name()).collect::<Vec<_>>().join(", "))]
#[diagnostic(code(E101), help("Align package name declarations in manifest files."))]
SplitIdentity { path: PathBuf, ids: Vec<PackageId> },
#[error("package `{id}` was not found in the workspace")]
#[diagnostic(
code(E102),
help("Verify package is included in workspace members in callisto.toml.")
)]
UnknownPackage { id: PackageId },
#[error("name `{name}` is ambiguous in this workspace; candidates: {}", .candidates.iter().map(|c| c.display_name()).collect::<Vec<_>>().join(", "))]
#[diagnostic(
code(E103),
help("Use fully-qualified package ID with ecosystem prefix (e.g. cargo:pkg).")
)]
AmbiguousName {
name: String,
candidates: Vec<PackageId>,
},
#[error("dependency cycle detected: {}", .cycle.iter().map(|i| i.display_name()).collect::<Vec<_>>().join(" -> "))]
#[diagnostic(
code(E104),
help("Refactor workspace dependencies to break the cyclic dependency chain.")
)]
Cycle { cycle: Vec<PackageId> },
#[error("cascade failed to converge after {iterations} iterations")]
#[diagnostic(
code(E105),
help("Check for oscillating peer or linked group dependencies.")
)]
CascadeNotConverged { iterations: usize },
#[error("fixed group `{group}` members have divergent on-disk versions: {}", .members.iter().map(|(id, v)| format!("{}={}", id.display_name(), v.render())).collect::<Vec<_>>().join(", "))]
#[diagnostic(
code(E106),
help("Align on-disk versions for all members of the fixed group.")
)]
FixedGroupDivergent {
group: GroupName,
members: Vec<(PackageId, callisto_model::Version)>,
},
#[error("group `{group}` members use incompatible versioning grammars: {}", .members.iter().map(|(id, v)| format!("{}={:?}", id.display_name(), v.grammar())).collect::<Vec<_>>().join(", "))]
#[diagnostic(code(E107))]
GroupGrammarMismatch {
group: GroupName,
members: Vec<(PackageId, callisto_model::Version)>,
},
#[error("group `{group}` lists member `{member}`, which was not found in the workspace")]
#[diagnostic(code(E108))]
MissingGroupMember { group: GroupName, member: String },
#[error("package `{package}` is listed in multiple conflicting groups: {}", .groups.iter().map(|g| g.as_str()).collect::<Vec<_>>().join(", "))]
#[diagnostic(code(E109))]
ConflictingGroupMembership {
package: PackageId,
groups: Vec<GroupName>,
},
#[error(
"version dependency edge from `{from}` to `{to}` involves incompatible grammars: {source}"
)]
GrammarMismatch {
from: PackageId,
to: PackageId,
#[source]
source: callisto_model::GrammarMismatch,
},
#[error("on-disk versions changed since plan was generated for `{package}`: expected {}, found {}", .expected.render(), .found.render())]
OnDiskVersionDrift {
package: PackageId,
expected: callisto_model::Version,
found: callisto_model::Version,
},
#[error("workspace root `{root_manifest}` has conflicting version updates: {details}")]
WorkspaceVersionConflict {
root_manifest: PathBuf,
details: String,
},
#[error("failed to parse .changeset/pre.json: {0}")]
#[diagnostic(
code(E114),
help("Check that .changeset/pre.json is valid JSON and was not partially written. Delete the file and re-run `callisto pre enter` to recover.")
)]
PreJson(callisto_format::PreJsonError),
#[error("failed to read .changeset/pre.json: {message}")]
#[diagnostic(
code(E115),
help("Check that .changeset/pre.json is readable. Delete the file and re-run `callisto pre enter` to recover.")
)]
PreJsonRead { message: String },
}
#[derive(Clone, Debug, thiserror::Error, miette::Diagnostic, PartialEq, Eq)]
#[non_exhaustive]
pub enum ConfigError {
#[error("failed to read `{path}`: {message}")]
#[diagnostic(code(E110))]
Read { path: PathBuf, message: String },
#[error("`{path}` is not valid TOML: {message}")]
#[diagnostic(code(E111), help("Verify callisto.toml TOML syntax formatting."))]
ParseToml { path: PathBuf, message: String },
#[error("`{path}` is not valid YAML: {message}")]
#[diagnostic(code(E112))]
ParseYaml { path: PathBuf, message: String },
#[error("[[package-set]] `{pattern}` matched no packages")]
PackageSetMatchedNothing { pattern: String },
#[error("[[package]] `{pattern}` matched no package")]
PackageMatchedNothing { pattern: String },
#[error("package `{package}` is claimed by more than one [[package-set]]: {}", .patterns.join(", "))]
OverlappingPackageSets {
package: String,
patterns: Vec<String>,
},
#[error("group `{group}` and group `{other}` both list `{member}`")]
ConflictingGroupNames {
group: GroupName,
other: GroupName,
member: String,
},
#[error("group `{group}` has no members")]
EmptyGroup { group: GroupName },
#[error("duplicate group name `{group}`")]
DuplicateGroupName { group: GroupName },
#[error("`publish-to` names registry key `{key}`, which no [registries.*] block defines")]
UnknownRegistry { key: String },
#[error("`{path}` sets unknown callisto key `{key}`")]
UnknownKey { path: PathBuf, key: String },
#[error("`cascade.bump-severity` is `{found}`; expected `patch` or `minor`")]
InvalidBumpSeverity { found: String },
#[error("`pre-major-inference` is `{found}`; expected `off`, `conservative`, or `conservative-feat`")]
InvalidPreMajorInference { found: String },
#[error(
"changesets.dir `{dir}` contains `..` path components and would escape the workspace root"
)]
#[diagnostic(
code(E116),
help("Use a path relative to the workspace root that does not contain '..' components.")
)]
InvalidChangesetsDir { dir: String },
#[error(transparent)]
Tag(#[from] TagTemplateError),
#[error(transparent)]
VersionParse(#[from] VersionParseError),
}