use crate::Purl;
use semver::VersionReq;
use std::{
borrow::Cow,
collections::HashMap,
fmt,
path::{Path, PathBuf},
};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Unit {
Project { manifest: PathBuf, name: String },
Workspace { manifest: PathBuf },
Global,
}
impl Ord for Unit {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match (self, other) {
(Unit::Workspace { .. }, Unit::Workspace { .. }) => std::cmp::Ordering::Equal,
(Unit::Workspace { .. }, _) => std::cmp::Ordering::Less,
(_, Unit::Workspace { .. }) => std::cmp::Ordering::Greater,
(Unit::Global, Unit::Global) => std::cmp::Ordering::Equal,
(Unit::Global, _) => std::cmp::Ordering::Greater,
(_, Unit::Global) => std::cmp::Ordering::Less,
_ => self.name().cmp(&other.name()),
}
}
}
impl PartialOrd for Unit {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Unit {
pub fn path(&self) -> Option<&Path> {
match self {
Unit::Project { manifest, .. } | Unit::Workspace { manifest, .. } => Some(manifest),
Unit::Global => None,
}
}
pub fn name(&self) -> Cow<'_, str> {
match self {
Unit::Project { name, .. } => name.into(),
Unit::Workspace { manifest, .. } => manifest
.parent()
.and_then(|p| p.file_name())
.and_then(|n| n.to_str())
.map(|n| format!("{n} (workspace)"))
.unwrap_or("workspace".into())
.into(),
Unit::Global => "global".into(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DepKind {
Normal,
Dev,
Build,
}
impl fmt::Display for DepKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
DepKind::Normal => write!(f, "dependencies"),
DepKind::Dev => write!(f, "dev-dependencies"),
DepKind::Build => write!(f, "build-dependencies"),
}
}
}
#[derive(Debug, Clone)]
pub struct Usage {
pub unit: Unit,
pub req: VersionReq,
pub kind: DepKind,
pub rename: Option<String>,
}
#[derive(Debug, Clone)]
pub struct Package {
pub purl: Purl,
pub usages: Vec<Usage>,
pub versions: Vec<PackageVersion>,
pub repository: Option<String>,
pub homepage: Option<String>,
}
pub type Packages = HashMap<Unit, Vec<(VersionReq, DepKind, Package)>>;
#[derive(Debug, Clone)]
pub struct PackageVersion {
pub version: semver::Version,
pub yanked: bool,
pub features: HashMap<String, Vec<String>>,
pub rust_version: Option<semver::Version>,
}