use std::fmt::Write;
use rustc_hash::FxHashMap;
use tracing::{Level, trace};
use uv_distribution_types::IndexUrl;
use uv_normalize::{ExtraName, GroupName, PackageName};
use uv_pep440::Version;
use uv_pep508::MarkerTree;
use uv_pypi_types::VerbatimParsedUrl;
use crate::pins::FilePins;
use crate::universal_marker::ConflictMarker;
use crate::{ResolverEnvironment, UniversalMarker};
#[derive(Debug)]
pub(crate) struct Resolution {
pub(crate) nodes: FxHashMap<ResolutionPackage, Version>,
pub(crate) edges: Vec<ResolutionDependencyEdge>,
pub(crate) pins: FilePins,
pub(crate) env: ResolverEnvironment,
}
impl Resolution {
pub(crate) fn trace_resolution(&self) {
if !tracing::enabled!(Level::TRACE) {
return;
}
trace!("Resolution: {:?}", self.env);
for edge in &self.edges {
trace!(
"Resolution edge: {} -> {}",
edge.from
.as_ref()
.map(PackageName::as_str)
.unwrap_or("ROOT"),
edge.to,
);
let mut msg = String::new();
write!(msg, "{}", edge.from_version).unwrap();
if let Some(ref extra) = edge.from_extra {
write!(msg, " (extra: {extra})").unwrap();
}
if let Some(ref dev) = edge.from_group {
write!(msg, " (group: {dev})").unwrap();
}
write!(msg, " -> ").unwrap();
write!(msg, "{}", edge.to_version).unwrap();
if let Some(ref extra) = edge.to_extra {
write!(msg, " (extra: {extra})").unwrap();
}
if let Some(ref dev) = edge.to_group {
write!(msg, " (group: {dev})").unwrap();
}
if let Some(marker) = edge.marker.contents() {
write!(msg, " ; {marker}").unwrap();
}
trace!("Resolution edge: {msg}");
}
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub(crate) struct ResolutionPackage {
pub(crate) name: PackageName,
pub(crate) extra: Option<ExtraName>,
pub(crate) dev: Option<GroupName>,
pub(crate) url: Option<VerbatimParsedUrl>,
pub(crate) index: Option<IndexUrl>,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub(crate) struct ResolutionDependencyEdge {
pub(crate) from: Option<PackageName>,
pub(crate) from_version: Version,
pub(crate) from_url: Option<VerbatimParsedUrl>,
pub(crate) from_index: Option<IndexUrl>,
pub(crate) from_extra: Option<ExtraName>,
pub(crate) from_group: Option<GroupName>,
pub(crate) to: PackageName,
pub(crate) to_version: Version,
pub(crate) to_url: Option<VerbatimParsedUrl>,
pub(crate) to_index: Option<IndexUrl>,
pub(crate) to_extra: Option<ExtraName>,
pub(crate) to_group: Option<GroupName>,
pub(crate) marker: MarkerTree,
}
impl ResolutionDependencyEdge {
pub(crate) fn universal_marker(&self) -> UniversalMarker {
UniversalMarker::new(self.marker, ConflictMarker::TRUE)
}
}