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::{MIN_VERSION, 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(|node| node.package.name.as_str())
.unwrap_or("ROOT"),
edge.to.package.name,
);
let mut msg = String::new();
write!(
msg,
"{}",
edge.from
.as_ref()
.map_or(&*MIN_VERSION, |node| &node.version)
)
.unwrap();
if let Some(extra) = edge
.from
.as_ref()
.and_then(|node| node.package.extra.as_ref())
{
write!(msg, " (extra: {extra})").unwrap();
}
if let Some(dev) = edge
.from
.as_ref()
.and_then(|node| node.package.dev.as_ref())
{
write!(msg, " (group: {dev})").unwrap();
}
write!(msg, " -> ").unwrap();
write!(msg, "{}", edge.to.version).unwrap();
if let Some(ref extra) = edge.to.package.extra {
write!(msg, " (extra: {extra})").unwrap();
}
if let Some(ref dev) = edge.to.package.dev {
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 ResolutionNode {
pub(crate) package: ResolutionPackage,
pub(crate) version: Version,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub(crate) struct ResolutionDependencyEdge {
pub(crate) from: Option<ResolutionNode>,
pub(crate) to: ResolutionNode,
pub(crate) marker: MarkerTree,
}
impl ResolutionDependencyEdge {
pub(crate) fn universal_marker(&self) -> UniversalMarker {
UniversalMarker::new(self.marker, ConflictMarker::TRUE)
}
}