diff --git a/Cargo.lock b/Cargo.lock index 16aa771e3..344653eba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2246,7 +2246,7 @@ dependencies = [ [[package]] name = "pubgrub" version = "0.2.1" -source = "git+https://github.com/zanieb/pubgrub?rev=866c0f2a87fee1e8abe804d40a2ee934de0973d7#866c0f2a87fee1e8abe804d40a2ee934de0973d7" +source = "git+https://github.com/zanieb/pubgrub?rev=c7cefdab4e69f123cba10bcc297f9ceed46a9dc5#c7cefdab4e69f123cba10bcc297f9ceed46a9dc5" dependencies = [ "indexmap 2.1.0", "log", diff --git a/Cargo.toml b/Cargo.toml index 9228fca79..03475c463 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,7 @@ owo-colors = { version = "3.5.0" } petgraph = { version = "0.6.4" } platform-info = { version = "2.0.2" } plist = { version = "1.6.0" } -pubgrub = { git = "https://github.com/zanieb/pubgrub", rev = "866c0f2a87fee1e8abe804d40a2ee934de0973d7" } +pubgrub = { git = "https://github.com/zanieb/pubgrub", rev = "c7cefdab4e69f123cba10bcc297f9ceed46a9dc5" } pyo3 = { version = "0.20.2" } pyo3-log = { version = "0.9.0"} pyproject-toml = { version = "0.8.1" } diff --git a/crates/puffin-resolver/src/pubgrub/report.rs b/crates/puffin-resolver/src/pubgrub/report.rs index c94708e58..95848c1d6 100644 --- a/crates/puffin-resolver/src/pubgrub/report.rs +++ b/crates/puffin-resolver/src/pubgrub/report.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; +use std::ops::Bound; use derivative::Derivative; use owo_colors::OwoColorize; @@ -35,7 +36,10 @@ impl ReportFormatter> for PubGrubReportFor if set.as_ref() == &Range::full() { format!("there are no versions of {package}") } else { - format!("there are no versions of {package}{set}") + format!( + "there are no versions of {package}{}", + PubGrubRange::new(&set) + ) } } External::UnavailableDependencies(package, set) => { @@ -43,7 +47,10 @@ impl ReportFormatter> for PubGrubReportFor if set.as_ref() == &Range::full() { format!("dependencies of {package} are unavailable") } else { - format!("dependencies of {package}{set} are unavailable") + format!( + "dependencies of {package}{} are unavailable", + PubGrubRange::new(&set) + ) } } External::UnusableDependencies(package, set, reason) => { @@ -55,7 +62,10 @@ impl ReportFormatter> for PubGrubReportFor if set.as_ref() == &Range::full() { format!("dependencies of {package} are unusable: {reason}") } else { - format!("dependencies of {package}{set} are unusable: {reason}",) + format!( + "dependencies of {package}{} are unusable: {reason}", + PubGrubRange::new(&set) + ) } } } else { @@ -63,7 +73,10 @@ impl ReportFormatter> for PubGrubReportFor if set.as_ref() == &Range::full() { format!("dependencies of {package} are unusable") } else { - format!("dependencies of {package}{set} are unusable") + format!( + "dependencies of {package}{} are unusable", + PubGrubRange::new(&set) + ) } } } @@ -75,20 +88,33 @@ impl ReportFormatter> for PubGrubReportFor { format!("{package} depends on {dependency}") } else if package_set.as_ref() == &Range::full() { - format!("{package} depends on {dependency}{dependency_set}") + format!( + "{package} depends on {dependency}{}", + PubGrubRange::new(&dependency_set) + ) } else if dependency_set.as_ref() == &Range::full() { if matches!(package, PubGrubPackage::Root(_)) { // Exclude the dummy version for root packages format!("{package} depends on {dependency}") } else { - format!("{package}{package_set} depends on {dependency}") + format!( + "{package}{} depends on {dependency}", + PubGrubRange::new(&package_set) + ) } } else { if matches!(package, PubGrubPackage::Root(_)) { // Exclude the dummy version for root packages - format!("{package} depends on {dependency}{dependency_set}") + format!( + "{package} depends on {dependency}{}", + PubGrubRange::new(&dependency_set) + ) } else { - format!("{package}{package_set} depends on {dependency}{dependency_set}") + format!( + "{package}{} depends on {dependency}{}", + PubGrubRange::new(&package_set), + PubGrubRange::new(&dependency_set) + ) } } } @@ -107,7 +133,7 @@ impl ReportFormatter> for PubGrubReportFor .unwrap_or(&vec![]) .iter(), ); - format!("{package}{range} is forbidden") + format!("{package}{} is forbidden", PubGrubRange::new(&range)) } [(package @ PubGrubPackage::Package(..), Term::Negative(range))] => { let range = range.simplify( @@ -116,7 +142,7 @@ impl ReportFormatter> for PubGrubReportFor .unwrap_or(&vec![]) .iter(), ); - format!("{package}{range} is mandatory") + format!("{package}{} is mandatory", PubGrubRange::new(&range)) } [(p1, Term::Positive(r1)), (p2, Term::Negative(r2))] => self.format_external( &External::FromDependencyOf((*p1).clone(), r1.clone(), (*p2).clone(), r2.clone()), @@ -265,14 +291,14 @@ impl std::fmt::Display for PubGrubHint { "hint".bold().cyan(), ":".bold(), package.bold(), - range.bold() + PubGrubRange::new(range).bold() ) } } } } -/// A derivative of the [Term] type with custom formatting. +/// A derivative of [Term] with custom formatting. struct PubGrubTerm { inner: Term>, } @@ -285,7 +311,7 @@ impl std::fmt::Display for PubGrubTerm { if let Some(version) = set.as_singleton() { write!(f, "!={version}") } else { - write!(f, "!( {set} )") + write!(f, "!( {} )", PubGrubRange::new(set)) } } } @@ -297,3 +323,46 @@ impl PubGrubTerm { PubGrubTerm { inner: term } } } + +/// A derivative of [Range] with custom formatting. +struct PubGrubRange<'a> { + inner: &'a Range, +} + +impl std::fmt::Display for PubGrubRange<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if self.inner.is_empty() { + write!(f, "∅")?; + } else { + for (idx, segment) in self.inner.iter().enumerate() { + if idx > 0 { + write!(f, " | ")?; + } + match segment { + (Bound::Unbounded, Bound::Unbounded) => write!(f, "*")?, + (Bound::Unbounded, Bound::Included(v)) => write!(f, "<={v}")?, + (Bound::Unbounded, Bound::Excluded(v)) => write!(f, "<{v}")?, + (Bound::Included(v), Bound::Unbounded) => write!(f, ">={v}")?, + (Bound::Included(v), Bound::Included(b)) => { + if v == b { + write!(f, "=={v}")?; + } else { + write!(f, ">={v}, <={b}")?; + } + } + (Bound::Included(v), Bound::Excluded(b)) => write!(f, ">={v}, <{b}")?, + (Bound::Excluded(v), Bound::Unbounded) => write!(f, ">{v}")?, + (Bound::Excluded(v), Bound::Included(b)) => write!(f, ">{v}, <={b}")?, + (Bound::Excluded(v), Bound::Excluded(b)) => write!(f, ">{v}, <{b}")?, + }; + } + } + Ok(()) + } +} + +impl PubGrubRange<'_> { + fn new(range: &Range) -> PubGrubRange { + PubGrubRange { inner: range } + } +}