Use bounded ranges rather than constructing manual ranges (#228)

I didn't realize this, but they made a bunch of improvements to how
PubGrub represents versions which lets us greatly simplify our own
PubGrub version wrapper
(https://github.com/pubgrub-rs/guide/pull/6/files).
This commit is contained in:
Charlie Marsh 2023-10-29 20:58:43 -07:00 committed by GitHub
parent fb2d4fc421
commit e73d3f0ff8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 74 deletions

View file

@ -1,4 +1,5 @@
use anyhow::Result;
use itertools::Itertools;
use pubgrub::range::Range;
use pep508_rs::{MarkerEnvironment, Requirement};
@ -8,7 +9,7 @@ use puffin_package::package_name::PackageName;
pub(crate) use crate::pubgrub::package::PubGrubPackage;
pub(crate) use crate::pubgrub::priority::{PubGrubPriorities, PubGrubPriority};
pub(crate) use crate::pubgrub::specifier::PubGrubSpecifier;
pub(crate) use crate::pubgrub::version::{PubGrubVersion, MAX_VERSION, MIN_VERSION};
pub(crate) use crate::pubgrub::version::{PubGrubVersion, MIN_VERSION};
mod package;
mod priority;
@ -67,19 +68,10 @@ pub(crate) fn version_range(
return Ok(Range::full());
};
let mut final_range = Range::full();
for spec in specifiers.iter() {
let spec_range =
PubGrubSpecifier::try_from(spec)?
.into_iter()
.fold(Range::empty(), |accum, range| {
accum.union(&if range.end < *MAX_VERSION {
Range::between(range.start, range.end)
} else {
Range::higher_than(range.start)
})
});
final_range = final_range.intersection(&spec_range);
}
Ok(final_range)
specifiers
.iter()
.map(PubGrubSpecifier::try_from)
.fold_ok(Range::full(), |range, specifier| {
range.intersection(&specifier.into())
})
}

View file

@ -1,21 +1,18 @@
use std::ops::Range;
use anyhow::Result;
use pubgrub::range::Range;
use pep440_rs::{Operator, VersionSpecifier};
use crate::pubgrub::version::{PubGrubVersion, MAX_VERSION, MIN_VERSION};
use crate::pubgrub::version::PubGrubVersion;
/// A range of versions that can be used to satisfy a requirement.
#[derive(Debug)]
pub(crate) struct PubGrubSpecifier(Vec<Range<PubGrubVersion>>);
pub(crate) struct PubGrubSpecifier(Range<PubGrubVersion>);
impl IntoIterator for PubGrubSpecifier {
type Item = Range<PubGrubVersion>;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
impl From<PubGrubSpecifier> for Range<PubGrubVersion> {
/// Convert a `PubGrub` specifier to a range of versions.
fn from(specifier: PubGrubSpecifier) -> Self {
specifier.0
}
}
@ -27,18 +24,15 @@ impl TryFrom<&VersionSpecifier> for PubGrubSpecifier {
let ranges = match specifier.operator() {
Operator::Equal => {
let version = PubGrubVersion::from(specifier.version().clone());
vec![version.clone()..version.next()]
Range::singleton(version)
}
Operator::ExactEqual => {
let version = PubGrubVersion::from(specifier.version().clone());
vec![version.clone()..version.next()]
Range::singleton(version)
}
Operator::NotEqual => {
let version = PubGrubVersion::from(specifier.version().clone());
vec![
MIN_VERSION.clone()..version.clone(),
version.next()..MAX_VERSION.clone(),
]
Range::singleton(version).complement()
}
Operator::TildeEqual => {
let [rest @ .., last, _] = specifier.version().release.as_slice() else {
@ -58,29 +52,16 @@ impl TryFrom<&VersionSpecifier> for PubGrubSpecifier {
.copied()
.collect(),
});
let lower = PubGrubVersion::from(specifier.version().clone());
vec![lower..upper]
let version = PubGrubVersion::from(specifier.version().clone());
Range::from_range_bounds(version..upper)
}
Operator::LessThan => {
// Per PEP 440: "The exclusive ordered comparison <V MUST NOT allow a pre-release of
// the specified version unless the specified version is itself a pre-release."
if specifier.version().any_prerelease() {
let version = PubGrubVersion::from(specifier.version().clone());
vec![MIN_VERSION.clone()..version.clone()]
} else {
let max_version = pep440_rs::Version {
post: None,
dev: Some(0),
local: None,
..specifier.version().clone()
};
let version = PubGrubVersion::from(max_version);
vec![MIN_VERSION.clone()..version.clone()]
}
let version = PubGrubVersion::from(specifier.version().clone());
Range::strictly_lower_than(version)
}
Operator::LessThanEqual => {
let version = PubGrubVersion::from(specifier.version().clone());
vec![MIN_VERSION.clone()..version.next()]
Range::lower_than(version)
}
Operator::GreaterThan => {
// Per PEP 440: "The exclusive ordered comparison >V MUST NOT allow a post-release of
@ -93,20 +74,18 @@ impl TryFrom<&VersionSpecifier> for PubGrubSpecifier {
} else {
low.post = Some(usize::MAX);
}
let version = PubGrubVersion::from(low);
vec![version..MAX_VERSION.clone()]
let version = PubGrubVersion::from(specifier.version().clone());
Range::strictly_higher_than(version)
}
Operator::GreaterThanEqual => {
let version = PubGrubVersion::from(specifier.version().clone());
vec![version..MAX_VERSION.clone()]
Range::higher_than(version)
}
Operator::EqualStar => {
let low = pep440_rs::Version {
dev: Some(0),
..specifier.version().clone()
};
let mut high = pep440_rs::Version {
dev: Some(0),
..specifier.version().clone()
@ -122,15 +101,13 @@ impl TryFrom<&VersionSpecifier> for PubGrubSpecifier {
} else {
*high.release.last_mut().unwrap() += 1;
}
vec![PubGrubVersion::from(low)..PubGrubVersion::from(high)]
Range::from_range_bounds(PubGrubVersion::from(low)..PubGrubVersion::from(high))
}
Operator::NotEqualStar => {
let low = pep440_rs::Version {
dev: Some(0),
..specifier.version().clone()
};
let mut high = pep440_rs::Version {
dev: Some(0),
..specifier.version().clone()
@ -146,11 +123,8 @@ impl TryFrom<&VersionSpecifier> for PubGrubSpecifier {
} else {
*high.release.last_mut().unwrap() += 1;
}
vec![
MIN_VERSION.clone()..PubGrubVersion::from(low),
PubGrubVersion::from(high)..MAX_VERSION.clone(),
]
Range::from_range_bounds(PubGrubVersion::from(low)..PubGrubVersion::from(high))
.complement()
}
};

View file

@ -62,14 +62,3 @@ impl From<PubGrubVersion> for pep440_rs::Version {
pub(crate) static MIN_VERSION: Lazy<PubGrubVersion> =
Lazy::new(|| PubGrubVersion::from(pep440_rs::Version::from_str("0a0.dev0").unwrap()));
pub(crate) static MAX_VERSION: Lazy<PubGrubVersion> = Lazy::new(|| {
PubGrubVersion(pep440_rs::Version {
epoch: usize::MAX,
release: vec![usize::MAX, usize::MAX, usize::MAX],
pre: None,
post: Some(usize::MAX),
dev: None,
local: None,
})
});