From c5d36598e178a04790180cd5cdfea790774a6852 Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Mon, 28 Aug 2023 10:00:39 +0200 Subject: [PATCH 1/6] feat: migrate strict version for version ranges --- .../src/match_spec/matcher.rs | 13 ++ .../rattler_conda_types/src/match_spec/mod.rs | 47 +++++ crates/rattler_conda_types/src/version/mod.rs | 66 ++++++- .../rattler_conda_types/src/version/parse.rs | 10 +- .../src/version_spec/constraint.rs | 55 +++--- .../src/version_spec/mod.rs | 180 +++++++++++------- .../src/version_spec/parse.rs | 71 +++---- .../src/version_spec/version_tree.rs | 40 ++-- 8 files changed, 335 insertions(+), 147 deletions(-) diff --git a/crates/rattler_conda_types/src/match_spec/matcher.rs b/crates/rattler_conda_types/src/match_spec/matcher.rs index 7ff468a9f..77ec39184 100644 --- a/crates/rattler_conda_types/src/match_spec/matcher.rs +++ b/crates/rattler_conda_types/src/match_spec/matcher.rs @@ -3,6 +3,7 @@ use std::{ fmt::{Display, Formatter}, str::FromStr, }; +use std::hash::{Hash, Hasher}; /// Match a given string either by exact match, glob or regex #[derive(Debug, Clone)] @@ -19,6 +20,18 @@ pub enum StringMatcher { Regex(regex::Regex), } + +impl Hash for StringMatcher { + fn hash(&self, state: &mut H) { + match self { + StringMatcher::Exact(s) => s.hash(state), + StringMatcher::Glob(pattern) => pattern.hash(state), + StringMatcher::Regex(regex) => regex.as_str().hash(state), + } + } +} + + impl PartialEq for StringMatcher { fn eq(&self, other: &Self) -> bool { match (self, other) { diff --git a/crates/rattler_conda_types/src/match_spec/mod.rs b/crates/rattler_conda_types/src/match_spec/mod.rs index 3b1a7ede6..e484314ca 100644 --- a/crates/rattler_conda_types/src/match_spec/mod.rs +++ b/crates/rattler_conda_types/src/match_spec/mod.rs @@ -3,6 +3,7 @@ use rattler_digest::{serde::SerializableHash, Md5Hash, Sha256Hash}; use serde::Serialize; use serde_with::{serde_as, skip_serializing_none}; use std::fmt::{Debug, Display, Formatter}; +use std::hash::{Hash, Hasher}; pub mod matcher; pub mod parse; @@ -344,6 +345,21 @@ impl MatchSpec { } } +impl Hash for MatchSpec { + fn hash(&self, state: &mut H) { + self.name.hash(state); + self.version.hash(state); + self.build.hash(state); + self.build_number.hash(state); + self.file_name.hash(state); + self.channel.hash(state); + self.subdir.hash(state); + self.namespace.hash(state); + self.md5.hash(state); + self.sha256.hash(state); + } +} + #[cfg(test)] mod tests { use std::str::FromStr; @@ -351,6 +367,7 @@ mod tests { use rattler_digest::{parse_digest_from_hex, Md5, Sha256}; use crate::{MatchSpec, NamelessMatchSpec, PackageRecord, Version}; + use std::hash::{Hash, Hasher}; #[test] fn test_matchspec_format_eq() { @@ -370,6 +387,36 @@ mod tests { assert_eq!(spec, rebuild_spec) } + #[test] + fn test_hash_match() { + // These should not be equal as they are unequal ranges + let spec1 = MatchSpec::from_str("tensorflow 2.6.*").unwrap(); + let spec2 = MatchSpec::from_str("tensorflow 2.6.*").unwrap(); + assert_eq!(spec1, spec2); + + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + let hash1 = spec1.hash(&mut hasher); + let hash2 = spec2.hash(&mut hasher); + + assert_eq!(hash1, hash2); + } + + #[test] + fn test_hash_no_match() { + let spec1 = MatchSpec::from_str("tensorflow 2.6.0.*").unwrap(); + let spec2 = MatchSpec::from_str("tensorflow 2.6.*").unwrap(); + dbg!(&spec1, &spec2); + assert_ne!(spec1, spec2); + + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + spec1.hash(&mut hasher); + let hash1 = hasher.finish(); + spec2.hash(&mut hasher); + let hash2 = hasher.finish(); + + assert_ne!(hash1, hash2); + } + #[test] fn test_digest_match() { let record = PackageRecord { diff --git a/crates/rattler_conda_types/src/version/mod.rs b/crates/rattler_conda_types/src/version/mod.rs index e575b7bf4..9f289e81a 100644 --- a/crates/rattler_conda_types/src/version/mod.rs +++ b/crates/rattler_conda_types/src/version/mod.rs @@ -940,6 +940,52 @@ impl<'v> SegmentIter<'v> { } } +/// Version that only has equality when it is exactly the same +/// e.g for [`Version`] 1.0.0 == 1.0 while in [`StrictVersion`] +/// this is not equal. Useful in ranges where we are talking +/// about equality over version ranges instead of specific +/// version instances +#[derive(Clone, Ord, Eq, Debug)] +pub struct StrictVersion(pub Version); + +impl PartialEq for StrictVersion { + fn eq(&self, other: &Self) -> bool { + // StrictVersion is only equal if the number + // of components are the same + // and the components are the same + self.0.components.len() == other.0.components.len() && self.0 == other.0 + } +} + +impl PartialOrd for StrictVersion { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.0.cmp(&other.0)) + } +} + +impl Display for StrictVersion { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl Hash for StrictVersion { + fn hash(&self, state: &mut H) { + fn hash_segments<'i, I: Iterator>, H: Hasher>( + state: &mut H, + segments: I, + ) { + for segment in segments { + segment.components().rev().for_each(|c| c.hash(state)); + } + } + + self.0.epoch().hash(state); + hash_segments(state, self.0.segments()); + hash_segments(state, self.0.local_segments()); + } +} + #[cfg(test)] mod test { use std::cmp::Ordering; @@ -950,6 +996,8 @@ mod test { use rand::seq::SliceRandom; + use crate::version::StrictVersion; + use super::Version; // Tests are inspired by: https://github.com/conda/conda/blob/33a142c16530fcdada6c377486f1c1a385738a96/tests/models/test_version.py @@ -1135,6 +1183,22 @@ mod test { assert_eq!(random_versions, parsed_versions); } + #[test] + fn strict_version_test() { + let v_1_0 = StrictVersion::from_str("1.0.0").unwrap(); + // Should be equal to itself + assert_eq!(v_1_0, v_1_0); + let v_1_0_0 = StrictVersion::from_str("1.0").unwrap(); + // Strict version should not discard zero's + assert_ne!(v_1_0, v_1_0_0); + // Ordering should stay the same as version + assert_eq!(v_1_0.cmp(&v_1_0_0), Ordering::Equal); + + // Hashing should consider v_1_0 and v_1_0_0 as unequal + assert_eq!(get_hash(&v_1_0), get_hash(&v_1_0)); + assert_ne!(get_hash(&v_1_0), get_hash(&v_1_0_0)); + } + #[test] fn bump() { assert_eq!( @@ -1158,7 +1222,7 @@ mod test { .starts_with(&Version::from_str("1.2").unwrap())); } - fn get_hash(spec: &Version) -> u64 { + fn get_hash(spec: &impl Hash) -> u64 { let mut s = DefaultHasher::new(); spec.hash(&mut s); s.finish() diff --git a/crates/rattler_conda_types/src/version/parse.rs b/crates/rattler_conda_types/src/version/parse.rs index 7f7d02da1..8f0bbe6f9 100644 --- a/crates/rattler_conda_types/src/version/parse.rs +++ b/crates/rattler_conda_types/src/version/parse.rs @@ -1,4 +1,4 @@ -use super::{Component, Version}; +use super::{Component, StrictVersion, Version}; use crate::version::flags::Flags; use crate::version::segment::Segment; use crate::version::{ComponentVec, SegmentVec}; @@ -437,6 +437,14 @@ impl FromStr for Version { } } +impl FromStr for StrictVersion { + type Err = ParseVersionError; + + fn from_str(s: &str) -> Result { + Ok(StrictVersion(Version::from_str(s)?)) + } +} + #[cfg(test)] mod test { use super::Version; diff --git a/crates/rattler_conda_types/src/version_spec/constraint.rs b/crates/rattler_conda_types/src/version_spec/constraint.rs index 889359751..cf35902db 100644 --- a/crates/rattler_conda_types/src/version_spec/constraint.rs +++ b/crates/rattler_conda_types/src/version_spec/constraint.rs @@ -1,8 +1,9 @@ use super::ParseConstraintError; -use super::VersionOperator; +use super::RangeOperator; use crate::version_spec::parse::constraint_parser; use crate::Version; use std::str::FromStr; +use crate::version_spec::EqualityOperator; /// A single version constraint (e.g. `>3.4.5` or `1.2.*`) #[allow(clippy::large_enum_variant)] @@ -12,7 +13,11 @@ pub(crate) enum Constraint { Any, /// Version comparison (e.g `>1.2.3`) - Comparison(VersionOperator, Version), + Comparison(RangeOperator, Version), + + /// Exact Version + Exact(EqualityOperator, Version), + } /// Returns true if the specified character is the first character of a version constraint. @@ -37,7 +42,7 @@ impl FromStr for Constraint { mod test { use super::Constraint; use crate::version_spec::constraint::ParseConstraintError; - use crate::version_spec::VersionOperator; + use crate::version_spec::{EqualityOperator, RangeOperator}; use crate::Version; use std::str::FromStr; @@ -91,63 +96,63 @@ mod test { assert_eq!( Constraint::from_str(">1.2.3"), Ok(Constraint::Comparison( - VersionOperator::Greater, + RangeOperator::Greater, Version::from_str("1.2.3").unwrap() )) ); assert_eq!( Constraint::from_str("<1.2.3"), Ok(Constraint::Comparison( - VersionOperator::Less, + RangeOperator::Less, Version::from_str("1.2.3").unwrap() )) ); assert_eq!( Constraint::from_str("=1.2.3"), Ok(Constraint::Comparison( - VersionOperator::StartsWith, + RangeOperator::StartsWith, Version::from_str("1.2.3").unwrap() )) ); assert_eq!( Constraint::from_str("==1.2.3"), - Ok(Constraint::Comparison( - VersionOperator::Equals, + Ok(Constraint::Exact( + EqualityOperator::Equals, Version::from_str("1.2.3").unwrap() )) ); assert_eq!( Constraint::from_str("!=1.2.3"), - Ok(Constraint::Comparison( - VersionOperator::NotEquals, + Ok(Constraint::Exact( + EqualityOperator::NotEquals, Version::from_str("1.2.3").unwrap() )) ); assert_eq!( Constraint::from_str("~=1.2.3"), Ok(Constraint::Comparison( - VersionOperator::Compatible, + RangeOperator::Compatible, Version::from_str("1.2.3").unwrap() )) ); assert_eq!( Constraint::from_str(">=1.2.3"), Ok(Constraint::Comparison( - VersionOperator::GreaterEquals, + RangeOperator::GreaterEquals, Version::from_str("1.2.3").unwrap() )) ); assert_eq!( Constraint::from_str("<=1.2.3"), Ok(Constraint::Comparison( - VersionOperator::LessEquals, + RangeOperator::LessEquals, Version::from_str("1.2.3").unwrap() )) ); assert_eq!( Constraint::from_str(">=1!1.2"), Ok(Constraint::Comparison( - VersionOperator::GreaterEquals, + RangeOperator::GreaterEquals, Version::from_str("1!1.2").unwrap() )) ); @@ -158,49 +163,49 @@ mod test { assert_eq!( Constraint::from_str("=1.2.*"), Ok(Constraint::Comparison( - VersionOperator::StartsWith, + RangeOperator::StartsWith, Version::from_str("1.2").unwrap() )) ); assert_eq!( Constraint::from_str("!=1.2.*"), Ok(Constraint::Comparison( - VersionOperator::NotStartsWith, + RangeOperator::NotStartsWith, Version::from_str("1.2").unwrap() )) ); assert_eq!( Constraint::from_str(">=1.2.*"), Ok(Constraint::Comparison( - VersionOperator::GreaterEquals, + RangeOperator::GreaterEquals, Version::from_str("1.2").unwrap() )) ); assert_eq!( Constraint::from_str("==1.2.*"), - Ok(Constraint::Comparison( - VersionOperator::Equals, + Ok(Constraint::Exact( + EqualityOperator::Equals, Version::from_str("1.2").unwrap() )) ); assert_eq!( Constraint::from_str(">1.2.*"), Ok(Constraint::Comparison( - VersionOperator::GreaterEquals, + RangeOperator::GreaterEquals, Version::from_str("1.2").unwrap() )) ); assert_eq!( Constraint::from_str("<=1.2.*"), Ok(Constraint::Comparison( - VersionOperator::LessEquals, + RangeOperator::LessEquals, Version::from_str("1.2").unwrap() )) ); assert_eq!( Constraint::from_str("<1.2.*"), Ok(Constraint::Comparison( - VersionOperator::Less, + RangeOperator::Less, Version::from_str("1.2").unwrap() )) ); @@ -211,7 +216,7 @@ mod test { assert_eq!( Constraint::from_str("1.2.*"), Ok(Constraint::Comparison( - VersionOperator::StartsWith, + RangeOperator::StartsWith, Version::from_str("1.2").unwrap() )) ); @@ -225,8 +230,8 @@ mod test { fn test_exact() { assert_eq!( Constraint::from_str("1.2.3"), - Ok(Constraint::Comparison( - VersionOperator::Equals, + Ok(Constraint::Exact( + EqualityOperator::Equals, Version::from_str("1.2.3").unwrap() )) ); diff --git a/crates/rattler_conda_types/src/version_spec/mod.rs b/crates/rattler_conda_types/src/version_spec/mod.rs index 7ea7a2530..333a1e4ab 100644 --- a/crates/rattler_conda_types/src/version_spec/mod.rs +++ b/crates/rattler_conda_types/src/version_spec/mod.rs @@ -17,13 +17,12 @@ use version_tree::VersionTree; pub(crate) use constraint::is_start_of_version_constraint; pub(crate) use parse::ParseConstraintError; +use crate::version::StrictVersion; /// An operator to compare two versions. #[allow(missing_docs)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize)] -pub enum VersionOperator { - Equals, - NotEquals, +pub enum RangeOperator { Greater, GreaterEquals, Less, @@ -34,24 +33,54 @@ pub enum VersionOperator { NotCompatible, } -impl VersionOperator { +impl RangeOperator { /// Returns the complement of the current operator. pub fn complement(self) -> Self { match self { - VersionOperator::Equals => VersionOperator::NotEquals, - VersionOperator::NotEquals => VersionOperator::Equals, - VersionOperator::Greater => VersionOperator::LessEquals, - VersionOperator::GreaterEquals => VersionOperator::Less, - VersionOperator::Less => VersionOperator::GreaterEquals, - VersionOperator::LessEquals => VersionOperator::Greater, - VersionOperator::StartsWith => VersionOperator::NotStartsWith, - VersionOperator::NotStartsWith => VersionOperator::StartsWith, - VersionOperator::Compatible => VersionOperator::NotCompatible, - VersionOperator::NotCompatible => VersionOperator::Compatible, + RangeOperator::Greater => RangeOperator::LessEquals, + RangeOperator::GreaterEquals => RangeOperator::Less, + RangeOperator::Less => RangeOperator::GreaterEquals, + RangeOperator::LessEquals => RangeOperator::Greater, + RangeOperator::StartsWith => RangeOperator::NotStartsWith, + RangeOperator::NotStartsWith => RangeOperator::StartsWith, + RangeOperator::Compatible => RangeOperator::NotCompatible, + RangeOperator::NotCompatible => RangeOperator::Compatible, } } } + + +/// An operator set a version equal to another +#[allow(missing_docs)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize)] +pub enum EqualityOperator { + Equals, + NotEquals, +} + +impl EqualityOperator { + /// Returns the complement of the current operator. + pub fn complement(self) -> Self { + match self { + EqualityOperator::Equals => EqualityOperator::NotEquals, + EqualityOperator::NotEquals => EqualityOperator::Equals, + } + } + +} + + +/// Range and equality operators combined +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize)] +pub enum VersionOperators { + /// Specifies a range of versions + Range(RangeOperator), + /// Specifies an exact version + Exact(EqualityOperator) +} + + /// Logical operator used two compare groups of version comparisions. E.g. `>=3.4,<4.0` or /// `>=3.4|<4.0`, #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize)] @@ -81,8 +110,10 @@ pub enum VersionSpec { None, /// Any version Any, - /// A specific version - Operator(VersionOperator, Version), + /// A version range + Range(RangeOperator, StrictVersion), + /// A exact version + Exact(EqualityOperator, Version), /// A group of version specifications Group(LogicalOperator, Vec), } @@ -114,7 +145,8 @@ impl FromStr for VersionSpec { .map_err(ParseVersionSpecError::InvalidConstraint)?; Ok(match constraint { Constraint::Any => VersionSpec::Any, - Constraint::Comparison(op, ver) => VersionSpec::Operator(op, ver), + Constraint::Comparison(op, ver) => VersionSpec::Range(op, StrictVersion(ver)), + Constraint::Exact(e, ver) => VersionSpec::Exact(e, ver), }) } VersionTree::Group(op, groups) => Ok(VersionSpec::Group( @@ -131,23 +163,31 @@ impl FromStr for VersionSpec { } } -impl Display for VersionOperator { +impl Display for RangeOperator { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + RangeOperator::Greater => write!(f, ">"), + RangeOperator::GreaterEquals => write!(f, ">="), + RangeOperator::Less => write!(f, "<"), + RangeOperator::LessEquals => write!(f, "<="), + RangeOperator::StartsWith => write!(f, "="), + RangeOperator::NotStartsWith => write!(f, "!=startswith"), + RangeOperator::Compatible => write!(f, "~="), + RangeOperator::NotCompatible => write!(f, "!~="), + } + } +} + +impl Display for EqualityOperator { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - VersionOperator::Equals => write!(f, "=="), - VersionOperator::NotEquals => write!(f, "!="), - VersionOperator::Greater => write!(f, ">"), - VersionOperator::GreaterEquals => write!(f, ">="), - VersionOperator::Less => write!(f, "<"), - VersionOperator::LessEquals => write!(f, "<="), - VersionOperator::StartsWith => write!(f, "="), - VersionOperator::NotStartsWith => write!(f, "!=startswith"), - VersionOperator::Compatible => write!(f, "~="), - VersionOperator::NotCompatible => write!(f, "!~="), + Self::Equals => write!(f, "=="), + Self::NotEquals => write!(f, "!="), } } } + impl Display for LogicalOperator { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { @@ -162,9 +202,12 @@ impl Display for VersionSpec { fn write(spec: &VersionSpec, f: &mut Formatter<'_>, part_of_or: bool) -> std::fmt::Result { match spec { VersionSpec::Any => write!(f, "*"), - VersionSpec::Operator(op, version) => match op { - VersionOperator::StartsWith => write!(f, "{}.*", version), - VersionOperator::NotStartsWith => write!(f, "!={}.*", version), + VersionSpec::Range(op, version) => match op { + RangeOperator::StartsWith => write!(f, "{}.*", version), + RangeOperator::NotStartsWith => write!(f, "!={}.*", version), + op => write!(f, "{}{}", op, version), + }, + VersionSpec::Exact(op, version) => match op { op => write!(f, "{}{}", op, version), }, VersionSpec::Group(op, group) => { @@ -206,21 +249,21 @@ impl VersionSpec { match self { VersionSpec::None => false, VersionSpec::Any => true, - VersionSpec::Operator(VersionOperator::Equals, limit) => limit == version, - VersionSpec::Operator(VersionOperator::NotEquals, limit) => limit != version, - VersionSpec::Operator(VersionOperator::Greater, limit) => version > limit, - VersionSpec::Operator(VersionOperator::GreaterEquals, limit) => version >= limit, - VersionSpec::Operator(VersionOperator::Less, limit) => version < limit, - VersionSpec::Operator(VersionOperator::LessEquals, limit) => version <= limit, - VersionSpec::Operator(VersionOperator::StartsWith, limit) => version.starts_with(limit), - VersionSpec::Operator(VersionOperator::NotStartsWith, limit) => { - !version.starts_with(limit) + VersionSpec::Exact(EqualityOperator::Equals, limit) => limit == version, + VersionSpec::Exact(EqualityOperator::NotEquals, limit) => limit != version, + VersionSpec::Range(RangeOperator::Greater, limit) => version > &limit.0, + VersionSpec::Range(RangeOperator::GreaterEquals, limit) => version >= &limit.0, + VersionSpec::Range(RangeOperator::Less, limit) => version < &limit.0, + VersionSpec::Range(RangeOperator::LessEquals, limit) => version <= &limit.0, + VersionSpec::Range(RangeOperator::StartsWith, limit) => version.starts_with(&limit.0), + VersionSpec::Range(RangeOperator::NotStartsWith, limit) => { + !version.starts_with(&limit.0) } - VersionSpec::Operator(VersionOperator::Compatible, limit) => { - version.compatible_with(limit) + VersionSpec::Range(RangeOperator::Compatible, limit) => { + version.compatible_with(&limit.0) } - VersionSpec::Operator(VersionOperator::NotCompatible, limit) => { - !version.compatible_with(limit) + VersionSpec::Range(RangeOperator::NotCompatible, limit) => { + !version.compatible_with(&limit.0) } VersionSpec::Group(LogicalOperator::And, group) => { group.iter().all(|spec| spec.matches(version)) @@ -234,24 +277,25 @@ impl VersionSpec { #[cfg(test)] mod tests { - use crate::version_spec::{LogicalOperator, VersionOperator}; + use crate::version_spec::{EqualityOperator, LogicalOperator, RangeOperator}; use crate::{Version, VersionSpec}; use std::str::FromStr; + use crate::version::StrictVersion; #[test] fn test_simple() { assert_eq!( VersionSpec::from_str("1.2.3"), - Ok(VersionSpec::Operator( - VersionOperator::Equals, + Ok(VersionSpec::Exact( + EqualityOperator::Equals, Version::from_str("1.2.3").unwrap() )) ); assert_eq!( VersionSpec::from_str(">=1.2.3"), - Ok(VersionSpec::Operator( - VersionOperator::GreaterEquals, - Version::from_str("1.2.3").unwrap() + Ok(VersionSpec::Range( + RangeOperator::GreaterEquals, + StrictVersion::from_str("1.2.3").unwrap() )) ); } @@ -263,13 +307,13 @@ mod tests { Ok(VersionSpec::Group( LogicalOperator::And, vec![ - VersionSpec::Operator( - VersionOperator::GreaterEquals, - Version::from_str("1.2.3").unwrap() + VersionSpec::Range( + RangeOperator::GreaterEquals, + StrictVersion::from_str("1.2.3").unwrap() ), - VersionSpec::Operator( - VersionOperator::Less, - Version::from_str("2.0.0").unwrap() + VersionSpec::Range( + RangeOperator::Less, + StrictVersion::from_str("2.0.0").unwrap() ), ] )) @@ -279,13 +323,13 @@ mod tests { Ok(VersionSpec::Group( LogicalOperator::Or, vec![ - VersionSpec::Operator( - VersionOperator::GreaterEquals, - Version::from_str("1.2.3").unwrap() + VersionSpec::Range( + RangeOperator::GreaterEquals, + StrictVersion::from_str("1.2.3").unwrap() ), - VersionSpec::Operator( - VersionOperator::Less, - Version::from_str("1.0.0").unwrap() + VersionSpec::Range( + RangeOperator::Less, + StrictVersion::from_str("1.0.0").unwrap() ), ] )) @@ -295,13 +339,13 @@ mod tests { Ok(VersionSpec::Group( LogicalOperator::Or, vec![ - VersionSpec::Operator( - VersionOperator::GreaterEquals, - Version::from_str("1.2.3").unwrap() + VersionSpec::Range( + RangeOperator::GreaterEquals, + StrictVersion::from_str("1.2.3").unwrap() ), - VersionSpec::Operator( - VersionOperator::Less, - Version::from_str("1.0.0").unwrap() + VersionSpec::Range( + RangeOperator::Less, + StrictVersion::from_str("1.0.0").unwrap() ), ] )) diff --git a/crates/rattler_conda_types/src/version_spec/parse.rs b/crates/rattler_conda_types/src/version_spec/parse.rs index a3a68dc76..9d136c9d9 100644 --- a/crates/rattler_conda_types/src/version_spec/parse.rs +++ b/crates/rattler_conda_types/src/version_spec/parse.rs @@ -1,6 +1,6 @@ use crate::version::parse::version_parser; use crate::version_spec::constraint::Constraint; -use crate::version_spec::VersionOperator; +use crate::version_spec::{EqualityOperator, RangeOperator, VersionOperators}; use crate::{ParseVersionError, ParseVersionErrorKind}; use nom::{ branch::alt, @@ -22,7 +22,7 @@ enum ParseVersionOperatorError<'i> { } /// Parses a version operator, returns an error if the operator is not recognized or not found. -fn operator_parser(input: &str) -> IResult<&str, VersionOperator, ParseVersionOperatorError> { +fn operator_parser(input: &str) -> IResult<&str, VersionOperators, ParseVersionOperatorError> { // Take anything that looks like an operator. let (rest, operator_str) = take_while1(|c| "=!<>~".contains(c))(input).map_err( |_: nom::Err>| { @@ -31,14 +31,14 @@ fn operator_parser(input: &str) -> IResult<&str, VersionOperator, ParseVersionOp )?; let op = match operator_str { - "==" => VersionOperator::Equals, - "!=" => VersionOperator::NotEquals, - "<=" => VersionOperator::LessEquals, - ">=" => VersionOperator::GreaterEquals, - "<" => VersionOperator::Less, - ">" => VersionOperator::Greater, - "=" => VersionOperator::StartsWith, - "~=" => VersionOperator::Compatible, + "==" => VersionOperators::Exact(EqualityOperator::Equals), + "!=" => VersionOperators::Exact(EqualityOperator::NotEquals), + "<=" => VersionOperators::Range(RangeOperator::LessEquals), + ">=" => VersionOperators::Range(RangeOperator::GreaterEquals), + "<" => VersionOperators::Range(RangeOperator::Less), + ">" => VersionOperators::Range(RangeOperator::Greater), + "=" => VersionOperators::Range(RangeOperator::StartsWith), + "~=" => VersionOperators::Range(RangeOperator::Compatible), _ => { return Err(nom::Err::Failure( ParseVersionOperatorError::InvalidOperator(operator_str), @@ -52,7 +52,7 @@ fn operator_parser(input: &str) -> IResult<&str, VersionOperator, ParseVersionOp #[derive(Debug, Clone, Error, Eq, PartialEq)] pub enum ParseConstraintError { #[error("'.' is incompatible with '{0}' operator'")] - GlobVersionIncompatibleWithOperator(VersionOperator), + GlobVersionIncompatibleWithOperator(RangeOperator), #[error("regex constraints are not supported")] RegexConstraintsNotSupported, #[error("unterminated unsupported regular expression")] @@ -142,18 +142,18 @@ fn logical_constraint_parser(input: &str) -> IResult<&str, Constraint, ParseCons let op = match (version_rest, op) { // The version was successfully parsed ("", Some(op)) => op, - ("", None) => VersionOperator::Equals, + ("", None) => VersionOperators::Exact(EqualityOperator::Equals), // The version ends in a wildcard pattern - ("*" | ".*", Some(VersionOperator::StartsWith)) => VersionOperator::StartsWith, - ("*" | ".*", Some(VersionOperator::GreaterEquals)) => VersionOperator::GreaterEquals, - ("*" | ".*", Some(VersionOperator::Greater)) => VersionOperator::GreaterEquals, - ("*" | ".*", Some(VersionOperator::NotEquals)) => VersionOperator::NotStartsWith, + ("*" | ".*", Some(VersionOperators::Range(RangeOperator::StartsWith))) => VersionOperators::Range(RangeOperator::StartsWith), + ("*" | ".*", Some(VersionOperators::Range(RangeOperator::GreaterEquals))) => VersionOperators::Range(RangeOperator::GreaterEquals), + ("*" | ".*", Some(VersionOperators::Range(RangeOperator::Greater))) => VersionOperators::Range(RangeOperator::GreaterEquals), + ("*" | ".*", Some(VersionOperators::Exact(EqualityOperator::NotEquals))) => VersionOperators::Range(RangeOperator::NotStartsWith), (glob @ "*" | glob @ ".*", Some(op)) => { tracing::warn!("Using {glob} with relational operator is superfluous and deprecated and will be removed in a future version of conda."); op } - ("*" | ".*", None) => VersionOperator::StartsWith, + ("*" | ".*", None) => VersionOperators::Range(RangeOperator::StartsWith), // The version string kinda looks like a regular expression. (version_remainder, _) if version_str.contains('*') || version_remainder.ends_with('$') => { @@ -173,7 +173,14 @@ fn logical_constraint_parser(input: &str) -> IResult<&str, Constraint, ParseCons } }; - Ok((rest, Constraint::Comparison(op, version))) + match op { + VersionOperators::Range(r) => { + Ok((rest, Constraint::Comparison(r, version))) + } + VersionOperators::Exact(e) => { + Ok((rest, Constraint::Exact(e, version))) + } + } } /// Parses a version constraint. @@ -195,32 +202,32 @@ mod test { fn test_operator_parser() { assert_eq!( operator_parser(">3.1"), - Ok(("3.1", VersionOperator::Greater)) + Ok(("3.1", VersionOperators::Range(RangeOperator::Greater))) ); assert_eq!( operator_parser(">=3.1"), - Ok(("3.1", VersionOperator::GreaterEquals)) + Ok(("3.1", VersionOperators::Range(RangeOperator::GreaterEquals))) ); - assert_eq!(operator_parser("<3.1"), Ok(("3.1", VersionOperator::Less))); + assert_eq!(operator_parser("<3.1"), Ok(("3.1", VersionOperators::Range(RangeOperator::Less)))); assert_eq!( operator_parser("<=3.1"), - Ok(("3.1", VersionOperator::LessEquals)) + Ok(("3.1", VersionOperators::Range(RangeOperator::LessEquals))) ); assert_eq!( operator_parser("==3.1"), - Ok(("3.1", VersionOperator::Equals)) + Ok(("3.1", VersionOperators::Exact(EqualityOperator::Equals))) ); assert_eq!( operator_parser("!=3.1"), - Ok(("3.1", VersionOperator::NotEquals)) + Ok(("3.1", VersionOperators::Exact(EqualityOperator::NotEquals))) ); assert_eq!( operator_parser("=3.1"), - Ok(("3.1", VersionOperator::StartsWith)) + Ok(("3.1", VersionOperators::Range(RangeOperator::StartsWith))) ); assert_eq!( operator_parser("~=3.1"), - Ok(("3.1", VersionOperator::Compatible)) + Ok(("3.1", VersionOperators::Range(RangeOperator::Compatible))) ); assert_eq!( @@ -265,7 +272,7 @@ mod test { logical_constraint_parser("3.1"), Ok(( "", - Constraint::Comparison(VersionOperator::Equals, Version::from_str("3.1").unwrap()) + Constraint::Exact(EqualityOperator::Equals, Version::from_str("3.1").unwrap()) )) ); @@ -273,7 +280,7 @@ mod test { logical_constraint_parser(">3.1"), Ok(( "", - Constraint::Comparison(VersionOperator::Greater, Version::from_str("3.1").unwrap()) + Constraint::Comparison(RangeOperator::Greater, Version::from_str("3.1").unwrap()) )) ); @@ -282,7 +289,7 @@ mod test { Ok(( "", Constraint::Comparison( - VersionOperator::StartsWith, + RangeOperator::StartsWith, Version::from_str("3.1").unwrap() ) )) @@ -293,7 +300,7 @@ mod test { Ok(( "", Constraint::Comparison( - VersionOperator::StartsWith, + RangeOperator::StartsWith, Version::from_str("3.1").unwrap() ) )) @@ -304,7 +311,7 @@ mod test { Ok(( "", Constraint::Comparison( - VersionOperator::Compatible, + RangeOperator::Compatible, Version::from_str("3.1").unwrap() ) )) @@ -315,7 +322,7 @@ mod test { Ok(( "", Constraint::Comparison( - VersionOperator::GreaterEquals, + RangeOperator::GreaterEquals, Version::from_str("3.1").unwrap() ) )) diff --git a/crates/rattler_conda_types/src/version_spec/version_tree.rs b/crates/rattler_conda_types/src/version_spec/version_tree.rs index e29338c70..96113fa42 100644 --- a/crates/rattler_conda_types/src/version_spec/version_tree.rs +++ b/crates/rattler_conda_types/src/version_spec/version_tree.rs @@ -1,4 +1,4 @@ -use crate::version_spec::{LogicalOperator, VersionOperator}; +use crate::version_spec::{EqualityOperator, LogicalOperator, RangeOperator, VersionOperators}; use nom::{ branch::alt, bytes::complete::{tag, take_while}, @@ -27,16 +27,16 @@ pub enum ParseVersionTreeError { /// A parser that parses version operators. fn parse_operator<'a, E: ParseError<&'a str>>( input: &'a str, -) -> Result<(&'a str, VersionOperator), nom::Err> { +) -> Result<(&'a str, VersionOperators), nom::Err> { alt(( - value(VersionOperator::Equals, tag("==")), - value(VersionOperator::StartsWith, tag("=")), - value(VersionOperator::NotEquals, tag("!=")), - value(VersionOperator::GreaterEquals, tag(">=")), - value(VersionOperator::Greater, tag(">")), - value(VersionOperator::LessEquals, tag("<=")), - value(VersionOperator::Less, tag("<")), - value(VersionOperator::Compatible, tag("~=")), + value(VersionOperators::Exact(EqualityOperator::Equals), tag("==")), + value(VersionOperators::Exact(EqualityOperator::NotEquals), tag("!=")), + value(VersionOperators::Range(RangeOperator::StartsWith), tag("=")), + value(VersionOperators::Range(RangeOperator::GreaterEquals), tag(">=")), + value(VersionOperators::Range(RangeOperator::Greater), tag(">")), + value(VersionOperators::Range(RangeOperator::LessEquals), tag("<=")), + value(VersionOperators::Range(RangeOperator::Less), tag("<")), + value(VersionOperators::Range(RangeOperator::Compatible), tag("~=")), ))(input) } @@ -186,7 +186,7 @@ impl<'a> TryFrom<&'a str> for VersionTree<'a> { mod tests { use super::{parse_operator, recognize_version, LogicalOperator, VersionTree}; use crate::version_spec::version_tree::{parse_version_epoch, recognize_constraint}; - use crate::version_spec::VersionOperator; + use crate::version_spec::{EqualityOperator, RangeOperator, VersionOperators}; use std::convert::TryFrom; #[test] @@ -245,32 +245,32 @@ mod tests { assert_eq!( parse_operator::("=="), - Ok(("", VersionOperator::Equals)) + Ok(("", VersionOperators::Exact(EqualityOperator::Equals))) ); assert_eq!( parse_operator::("!="), - Ok(("", VersionOperator::NotEquals)) + Ok(("", VersionOperators::Exact(EqualityOperator::NotEquals))) ); assert_eq!( parse_operator::(">"), - Ok(("", VersionOperator::Greater)) + Ok(("", VersionOperators::Range(RangeOperator::Greater))) ); assert_eq!( parse_operator::(">="), - Ok(("", VersionOperator::GreaterEquals)) + Ok(("", VersionOperators::Range(RangeOperator::GreaterEquals))) ); - assert_eq!(parse_operator::("<"), Ok(("", VersionOperator::Less))); + assert_eq!(parse_operator::("<"), Ok(("", VersionOperators::Range(RangeOperator::Less)))); assert_eq!( parse_operator::("<="), - Ok(("", VersionOperator::LessEquals)) + Ok(("", VersionOperators::Range(RangeOperator::LessEquals))) ); assert_eq!( parse_operator::("="), - Ok(("", VersionOperator::StartsWith)) + Ok(("", VersionOperators::Range(RangeOperator::StartsWith))) ); assert_eq!( parse_operator::("~="), - Ok(("", VersionOperator::Compatible)) + Ok(("", VersionOperators::Range(RangeOperator::Compatible))) ); // Anything else is an error @@ -280,7 +280,7 @@ mod tests { // Only the operator is parsed assert_eq!( parse_operator::(">=3.8"), - Ok(("3.8", VersionOperator::GreaterEquals)) + Ok(("3.8", VersionOperators::Range(RangeOperator::GreaterEquals))) ); } From 865084cc1898fb97502477eefbcc134f5a29c7a4 Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Mon, 28 Aug 2023 13:37:55 +0200 Subject: [PATCH 2/6] fix: formatting --- .../src/match_spec/matcher.rs | 4 +-- .../src/version_spec/constraint.rs | 3 +- .../src/version_spec/mod.rs | 16 ++++------ .../src/version_spec/parse.rs | 29 ++++++++++++------- .../src/version_spec/version_tree.rs | 25 ++++++++++++---- 5 files changed, 46 insertions(+), 31 deletions(-) diff --git a/crates/rattler_conda_types/src/match_spec/matcher.rs b/crates/rattler_conda_types/src/match_spec/matcher.rs index 77ec39184..2bb9ddef2 100644 --- a/crates/rattler_conda_types/src/match_spec/matcher.rs +++ b/crates/rattler_conda_types/src/match_spec/matcher.rs @@ -1,9 +1,9 @@ use serde::{Serialize, Serializer}; +use std::hash::{Hash, Hasher}; use std::{ fmt::{Display, Formatter}, str::FromStr, }; -use std::hash::{Hash, Hasher}; /// Match a given string either by exact match, glob or regex #[derive(Debug, Clone)] @@ -20,7 +20,6 @@ pub enum StringMatcher { Regex(regex::Regex), } - impl Hash for StringMatcher { fn hash(&self, state: &mut H) { match self { @@ -31,7 +30,6 @@ impl Hash for StringMatcher { } } - impl PartialEq for StringMatcher { fn eq(&self, other: &Self) -> bool { match (self, other) { diff --git a/crates/rattler_conda_types/src/version_spec/constraint.rs b/crates/rattler_conda_types/src/version_spec/constraint.rs index cf35902db..5759cc8c2 100644 --- a/crates/rattler_conda_types/src/version_spec/constraint.rs +++ b/crates/rattler_conda_types/src/version_spec/constraint.rs @@ -1,9 +1,9 @@ use super::ParseConstraintError; use super::RangeOperator; use crate::version_spec::parse::constraint_parser; +use crate::version_spec::EqualityOperator; use crate::Version; use std::str::FromStr; -use crate::version_spec::EqualityOperator; /// A single version constraint (e.g. `>3.4.5` or `1.2.*`) #[allow(clippy::large_enum_variant)] @@ -17,7 +17,6 @@ pub(crate) enum Constraint { /// Exact Version Exact(EqualityOperator, Version), - } /// Returns true if the specified character is the first character of a version constraint. diff --git a/crates/rattler_conda_types/src/version_spec/mod.rs b/crates/rattler_conda_types/src/version_spec/mod.rs index 333a1e4ab..b6b549553 100644 --- a/crates/rattler_conda_types/src/version_spec/mod.rs +++ b/crates/rattler_conda_types/src/version_spec/mod.rs @@ -15,9 +15,9 @@ use std::str::FromStr; use thiserror::Error; use version_tree::VersionTree; +use crate::version::StrictVersion; pub(crate) use constraint::is_start_of_version_constraint; pub(crate) use parse::ParseConstraintError; -use crate::version::StrictVersion; /// An operator to compare two versions. #[allow(missing_docs)] @@ -49,8 +49,6 @@ impl RangeOperator { } } - - /// An operator set a version equal to another #[allow(missing_docs)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize)] @@ -67,20 +65,17 @@ impl EqualityOperator { EqualityOperator::NotEquals => EqualityOperator::Equals, } } - } - /// Range and equality operators combined #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize)] pub enum VersionOperators { /// Specifies a range of versions Range(RangeOperator), /// Specifies an exact version - Exact(EqualityOperator) + Exact(EqualityOperator), } - /// Logical operator used two compare groups of version comparisions. E.g. `>=3.4,<4.0` or /// `>=3.4|<4.0`, #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize)] @@ -145,7 +140,9 @@ impl FromStr for VersionSpec { .map_err(ParseVersionSpecError::InvalidConstraint)?; Ok(match constraint { Constraint::Any => VersionSpec::Any, - Constraint::Comparison(op, ver) => VersionSpec::Range(op, StrictVersion(ver)), + Constraint::Comparison(op, ver) => { + VersionSpec::Range(op, StrictVersion(ver)) + } Constraint::Exact(e, ver) => VersionSpec::Exact(e, ver), }) } @@ -187,7 +184,6 @@ impl Display for EqualityOperator { } } - impl Display for LogicalOperator { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { @@ -277,10 +273,10 @@ impl VersionSpec { #[cfg(test)] mod tests { + use crate::version::StrictVersion; use crate::version_spec::{EqualityOperator, LogicalOperator, RangeOperator}; use crate::{Version, VersionSpec}; use std::str::FromStr; - use crate::version::StrictVersion; #[test] fn test_simple() { diff --git a/crates/rattler_conda_types/src/version_spec/parse.rs b/crates/rattler_conda_types/src/version_spec/parse.rs index 9d136c9d9..fcb9d7388 100644 --- a/crates/rattler_conda_types/src/version_spec/parse.rs +++ b/crates/rattler_conda_types/src/version_spec/parse.rs @@ -145,10 +145,18 @@ fn logical_constraint_parser(input: &str) -> IResult<&str, Constraint, ParseCons ("", None) => VersionOperators::Exact(EqualityOperator::Equals), // The version ends in a wildcard pattern - ("*" | ".*", Some(VersionOperators::Range(RangeOperator::StartsWith))) => VersionOperators::Range(RangeOperator::StartsWith), - ("*" | ".*", Some(VersionOperators::Range(RangeOperator::GreaterEquals))) => VersionOperators::Range(RangeOperator::GreaterEquals), - ("*" | ".*", Some(VersionOperators::Range(RangeOperator::Greater))) => VersionOperators::Range(RangeOperator::GreaterEquals), - ("*" | ".*", Some(VersionOperators::Exact(EqualityOperator::NotEquals))) => VersionOperators::Range(RangeOperator::NotStartsWith), + ("*" | ".*", Some(VersionOperators::Range(RangeOperator::StartsWith))) => { + VersionOperators::Range(RangeOperator::StartsWith) + } + ("*" | ".*", Some(VersionOperators::Range(RangeOperator::GreaterEquals))) => { + VersionOperators::Range(RangeOperator::GreaterEquals) + } + ("*" | ".*", Some(VersionOperators::Range(RangeOperator::Greater))) => { + VersionOperators::Range(RangeOperator::GreaterEquals) + } + ("*" | ".*", Some(VersionOperators::Exact(EqualityOperator::NotEquals))) => { + VersionOperators::Range(RangeOperator::NotStartsWith) + } (glob @ "*" | glob @ ".*", Some(op)) => { tracing::warn!("Using {glob} with relational operator is superfluous and deprecated and will be removed in a future version of conda."); op @@ -174,12 +182,8 @@ fn logical_constraint_parser(input: &str) -> IResult<&str, Constraint, ParseCons }; match op { - VersionOperators::Range(r) => { - Ok((rest, Constraint::Comparison(r, version))) - } - VersionOperators::Exact(e) => { - Ok((rest, Constraint::Exact(e, version))) - } + VersionOperators::Range(r) => Ok((rest, Constraint::Comparison(r, version))), + VersionOperators::Exact(e) => Ok((rest, Constraint::Exact(e, version))), } } @@ -208,7 +212,10 @@ mod test { operator_parser(">=3.1"), Ok(("3.1", VersionOperators::Range(RangeOperator::GreaterEquals))) ); - assert_eq!(operator_parser("<3.1"), Ok(("3.1", VersionOperators::Range(RangeOperator::Less)))); + assert_eq!( + operator_parser("<3.1"), + Ok(("3.1", VersionOperators::Range(RangeOperator::Less))) + ); assert_eq!( operator_parser("<=3.1"), Ok(("3.1", VersionOperators::Range(RangeOperator::LessEquals))) diff --git a/crates/rattler_conda_types/src/version_spec/version_tree.rs b/crates/rattler_conda_types/src/version_spec/version_tree.rs index 96113fa42..98af161cd 100644 --- a/crates/rattler_conda_types/src/version_spec/version_tree.rs +++ b/crates/rattler_conda_types/src/version_spec/version_tree.rs @@ -30,13 +30,25 @@ fn parse_operator<'a, E: ParseError<&'a str>>( ) -> Result<(&'a str, VersionOperators), nom::Err> { alt(( value(VersionOperators::Exact(EqualityOperator::Equals), tag("==")), - value(VersionOperators::Exact(EqualityOperator::NotEquals), tag("!=")), + value( + VersionOperators::Exact(EqualityOperator::NotEquals), + tag("!="), + ), value(VersionOperators::Range(RangeOperator::StartsWith), tag("=")), - value(VersionOperators::Range(RangeOperator::GreaterEquals), tag(">=")), + value( + VersionOperators::Range(RangeOperator::GreaterEquals), + tag(">="), + ), value(VersionOperators::Range(RangeOperator::Greater), tag(">")), - value(VersionOperators::Range(RangeOperator::LessEquals), tag("<=")), + value( + VersionOperators::Range(RangeOperator::LessEquals), + tag("<="), + ), value(VersionOperators::Range(RangeOperator::Less), tag("<")), - value(VersionOperators::Range(RangeOperator::Compatible), tag("~=")), + value( + VersionOperators::Range(RangeOperator::Compatible), + tag("~="), + ), ))(input) } @@ -259,7 +271,10 @@ mod tests { parse_operator::(">="), Ok(("", VersionOperators::Range(RangeOperator::GreaterEquals))) ); - assert_eq!(parse_operator::("<"), Ok(("", VersionOperators::Range(RangeOperator::Less)))); + assert_eq!( + parse_operator::("<"), + Ok(("", VersionOperators::Range(RangeOperator::Less))) + ); assert_eq!( parse_operator::("<="), Ok(("", VersionOperators::Range(RangeOperator::LessEquals))) From 22eb64f665fdf9ceae0a43ae0da76ff237450853 Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Mon, 28 Aug 2023 14:49:06 +0200 Subject: [PATCH 3/6] feat: splits up operator further --- .../src/version_spec/constraint.rs | 27 +++-- .../src/version_spec/mod.rs | 103 +++++++++++------- .../src/version_spec/parse.rs | 37 ++++--- .../src/version_spec/version_tree.rs | 25 ++++- 4 files changed, 118 insertions(+), 74 deletions(-) diff --git a/crates/rattler_conda_types/src/version_spec/constraint.rs b/crates/rattler_conda_types/src/version_spec/constraint.rs index 5759cc8c2..a98137089 100644 --- a/crates/rattler_conda_types/src/version_spec/constraint.rs +++ b/crates/rattler_conda_types/src/version_spec/constraint.rs @@ -1,7 +1,7 @@ use super::ParseConstraintError; use super::RangeOperator; use crate::version_spec::parse::constraint_parser; -use crate::version_spec::EqualityOperator; +use crate::version_spec::{EqualityOperator, StrictRangeOperator}; use crate::Version; use std::str::FromStr; @@ -15,6 +15,9 @@ pub(crate) enum Constraint { /// Version comparison (e.g `>1.2.3`) Comparison(RangeOperator, Version), + /// Strict comparison (e.g `~=1.2.3`) + StrictComparison(StrictRangeOperator, Version), + /// Exact Version Exact(EqualityOperator, Version), } @@ -41,7 +44,7 @@ impl FromStr for Constraint { mod test { use super::Constraint; use crate::version_spec::constraint::ParseConstraintError; - use crate::version_spec::{EqualityOperator, RangeOperator}; + use crate::version_spec::{EqualityOperator, RangeOperator, StrictRangeOperator}; use crate::Version; use std::str::FromStr; @@ -108,8 +111,8 @@ mod test { ); assert_eq!( Constraint::from_str("=1.2.3"), - Ok(Constraint::Comparison( - RangeOperator::StartsWith, + Ok(Constraint::StrictComparison( + StrictRangeOperator::StartsWith, Version::from_str("1.2.3").unwrap() )) ); @@ -129,8 +132,8 @@ mod test { ); assert_eq!( Constraint::from_str("~=1.2.3"), - Ok(Constraint::Comparison( - RangeOperator::Compatible, + Ok(Constraint::StrictComparison( + StrictRangeOperator::Compatible, Version::from_str("1.2.3").unwrap() )) ); @@ -161,15 +164,15 @@ mod test { fn test_glob_op() { assert_eq!( Constraint::from_str("=1.2.*"), - Ok(Constraint::Comparison( - RangeOperator::StartsWith, + Ok(Constraint::StrictComparison( + StrictRangeOperator::StartsWith, Version::from_str("1.2").unwrap() )) ); assert_eq!( Constraint::from_str("!=1.2.*"), - Ok(Constraint::Comparison( - RangeOperator::NotStartsWith, + Ok(Constraint::StrictComparison( + StrictRangeOperator::NotStartsWith, Version::from_str("1.2").unwrap() )) ); @@ -214,8 +217,8 @@ mod test { fn test_starts_with() { assert_eq!( Constraint::from_str("1.2.*"), - Ok(Constraint::Comparison( - RangeOperator::StartsWith, + Ok(Constraint::StrictComparison( + StrictRangeOperator::StartsWith, Version::from_str("1.2").unwrap() )) ); diff --git a/crates/rattler_conda_types/src/version_spec/mod.rs b/crates/rattler_conda_types/src/version_spec/mod.rs index b6b549553..33ba85485 100644 --- a/crates/rattler_conda_types/src/version_spec/mod.rs +++ b/crates/rattler_conda_types/src/version_spec/mod.rs @@ -27,10 +27,6 @@ pub enum RangeOperator { GreaterEquals, Less, LessEquals, - StartsWith, - NotStartsWith, - Compatible, - NotCompatible, } impl RangeOperator { @@ -41,10 +37,27 @@ impl RangeOperator { RangeOperator::GreaterEquals => RangeOperator::Less, RangeOperator::Less => RangeOperator::GreaterEquals, RangeOperator::LessEquals => RangeOperator::Greater, - RangeOperator::StartsWith => RangeOperator::NotStartsWith, - RangeOperator::NotStartsWith => RangeOperator::StartsWith, - RangeOperator::Compatible => RangeOperator::NotCompatible, - RangeOperator::NotCompatible => RangeOperator::Compatible, + } + } +} + +#[allow(missing_docs)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize)] +pub enum StrictRangeOperator { + StartsWith, + NotStartsWith, + Compatible, + NotCompatible, +} + +impl StrictRangeOperator { + /// Returns the complement of the current operator. + pub fn complement(self) -> Self { + match self { + StrictRangeOperator::StartsWith => StrictRangeOperator::NotStartsWith, + StrictRangeOperator::NotStartsWith => StrictRangeOperator::StartsWith, + StrictRangeOperator::Compatible => StrictRangeOperator::NotCompatible, + StrictRangeOperator::NotCompatible => StrictRangeOperator::Compatible, } } } @@ -72,6 +85,8 @@ impl EqualityOperator { pub enum VersionOperators { /// Specifies a range of versions Range(RangeOperator), + /// Specifies a range of versions using the strict operator + StrictRange(StrictRangeOperator), /// Specifies an exact version Exact(EqualityOperator), } @@ -106,7 +121,9 @@ pub enum VersionSpec { /// Any version Any, /// A version range - Range(RangeOperator, StrictVersion), + Range(RangeOperator, Version), + /// A version range using the strict operator + StrictRange(StrictRangeOperator, StrictVersion), /// A exact version Exact(EqualityOperator, Version), /// A group of version specifications @@ -140,8 +157,9 @@ impl FromStr for VersionSpec { .map_err(ParseVersionSpecError::InvalidConstraint)?; Ok(match constraint { Constraint::Any => VersionSpec::Any, - Constraint::Comparison(op, ver) => { - VersionSpec::Range(op, StrictVersion(ver)) + Constraint::Comparison(op, ver) => VersionSpec::Range(op, ver), + Constraint::StrictComparison(op, ver) => { + VersionSpec::StrictRange(op, StrictVersion(ver)) } Constraint::Exact(e, ver) => VersionSpec::Exact(e, ver), }) @@ -167,10 +185,17 @@ impl Display for RangeOperator { RangeOperator::GreaterEquals => write!(f, ">="), RangeOperator::Less => write!(f, "<"), RangeOperator::LessEquals => write!(f, "<="), - RangeOperator::StartsWith => write!(f, "="), - RangeOperator::NotStartsWith => write!(f, "!=startswith"), - RangeOperator::Compatible => write!(f, "~="), - RangeOperator::NotCompatible => write!(f, "!~="), + } + } +} + +impl Display for StrictRangeOperator { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + StrictRangeOperator::StartsWith => write!(f, "="), + StrictRangeOperator::NotStartsWith => write!(f, "!=startswith"), + StrictRangeOperator::Compatible => write!(f, "~="), + StrictRangeOperator::NotCompatible => write!(f, "!~="), } } } @@ -198,9 +223,12 @@ impl Display for VersionSpec { fn write(spec: &VersionSpec, f: &mut Formatter<'_>, part_of_or: bool) -> std::fmt::Result { match spec { VersionSpec::Any => write!(f, "*"), + VersionSpec::StrictRange(op, version) => match op { + StrictRangeOperator::StartsWith => write!(f, "{}.*", version), + StrictRangeOperator::NotStartsWith => write!(f, "!={}.*", version), + op => write!(f, "{}{}", op, version), + }, VersionSpec::Range(op, version) => match op { - RangeOperator::StartsWith => write!(f, "{}.*", version), - RangeOperator::NotStartsWith => write!(f, "!={}.*", version), op => write!(f, "{}{}", op, version), }, VersionSpec::Exact(op, version) => match op { @@ -247,18 +275,20 @@ impl VersionSpec { VersionSpec::Any => true, VersionSpec::Exact(EqualityOperator::Equals, limit) => limit == version, VersionSpec::Exact(EqualityOperator::NotEquals, limit) => limit != version, - VersionSpec::Range(RangeOperator::Greater, limit) => version > &limit.0, - VersionSpec::Range(RangeOperator::GreaterEquals, limit) => version >= &limit.0, - VersionSpec::Range(RangeOperator::Less, limit) => version < &limit.0, - VersionSpec::Range(RangeOperator::LessEquals, limit) => version <= &limit.0, - VersionSpec::Range(RangeOperator::StartsWith, limit) => version.starts_with(&limit.0), - VersionSpec::Range(RangeOperator::NotStartsWith, limit) => { + VersionSpec::Range(RangeOperator::Greater, limit) => version > &limit, + VersionSpec::Range(RangeOperator::GreaterEquals, limit) => version >= &limit, + VersionSpec::Range(RangeOperator::Less, limit) => version < &limit, + VersionSpec::Range(RangeOperator::LessEquals, limit) => version <= &limit, + VersionSpec::StrictRange(StrictRangeOperator::StartsWith, limit) => { + version.starts_with(&limit.0) + } + VersionSpec::StrictRange(StrictRangeOperator::NotStartsWith, limit) => { !version.starts_with(&limit.0) } - VersionSpec::Range(RangeOperator::Compatible, limit) => { + VersionSpec::StrictRange(StrictRangeOperator::Compatible, limit) => { version.compatible_with(&limit.0) } - VersionSpec::Range(RangeOperator::NotCompatible, limit) => { + VersionSpec::StrictRange(StrictRangeOperator::NotCompatible, limit) => { !version.compatible_with(&limit.0) } VersionSpec::Group(LogicalOperator::And, group) => { @@ -291,7 +321,7 @@ mod tests { VersionSpec::from_str(">=1.2.3"), Ok(VersionSpec::Range( RangeOperator::GreaterEquals, - StrictVersion::from_str("1.2.3").unwrap() + Version::from_str("1.2.3").unwrap() )) ); } @@ -305,12 +335,9 @@ mod tests { vec![ VersionSpec::Range( RangeOperator::GreaterEquals, - StrictVersion::from_str("1.2.3").unwrap() - ), - VersionSpec::Range( - RangeOperator::Less, - StrictVersion::from_str("2.0.0").unwrap() + Version::from_str("1.2.3").unwrap() ), + VersionSpec::Range(RangeOperator::Less, Version::from_str("2.0.0").unwrap()), ] )) ); @@ -321,12 +348,9 @@ mod tests { vec![ VersionSpec::Range( RangeOperator::GreaterEquals, - StrictVersion::from_str("1.2.3").unwrap() - ), - VersionSpec::Range( - RangeOperator::Less, - StrictVersion::from_str("1.0.0").unwrap() + Version::from_str("1.2.3").unwrap() ), + VersionSpec::Range(RangeOperator::Less, Version::from_str("1.0.0").unwrap()), ] )) ); @@ -337,12 +361,9 @@ mod tests { vec![ VersionSpec::Range( RangeOperator::GreaterEquals, - StrictVersion::from_str("1.2.3").unwrap() - ), - VersionSpec::Range( - RangeOperator::Less, - StrictVersion::from_str("1.0.0").unwrap() + Version::from_str("1.2.3").unwrap() ), + VersionSpec::Range(RangeOperator::Less, Version::from_str("1.0.0").unwrap()), ] )) ); diff --git a/crates/rattler_conda_types/src/version_spec/parse.rs b/crates/rattler_conda_types/src/version_spec/parse.rs index fcb9d7388..728f5a9a4 100644 --- a/crates/rattler_conda_types/src/version_spec/parse.rs +++ b/crates/rattler_conda_types/src/version_spec/parse.rs @@ -1,6 +1,6 @@ use crate::version::parse::version_parser; use crate::version_spec::constraint::Constraint; -use crate::version_spec::{EqualityOperator, RangeOperator, VersionOperators}; +use crate::version_spec::{EqualityOperator, RangeOperator, StrictRangeOperator, VersionOperators}; use crate::{ParseVersionError, ParseVersionErrorKind}; use nom::{ branch::alt, @@ -37,8 +37,8 @@ fn operator_parser(input: &str) -> IResult<&str, VersionOperators, ParseVersionO ">=" => VersionOperators::Range(RangeOperator::GreaterEquals), "<" => VersionOperators::Range(RangeOperator::Less), ">" => VersionOperators::Range(RangeOperator::Greater), - "=" => VersionOperators::Range(RangeOperator::StartsWith), - "~=" => VersionOperators::Range(RangeOperator::Compatible), + "=" => VersionOperators::StrictRange(StrictRangeOperator::StartsWith), + "~=" => VersionOperators::StrictRange(StrictRangeOperator::Compatible), _ => { return Err(nom::Err::Failure( ParseVersionOperatorError::InvalidOperator(operator_str), @@ -145,8 +145,8 @@ fn logical_constraint_parser(input: &str) -> IResult<&str, Constraint, ParseCons ("", None) => VersionOperators::Exact(EqualityOperator::Equals), // The version ends in a wildcard pattern - ("*" | ".*", Some(VersionOperators::Range(RangeOperator::StartsWith))) => { - VersionOperators::Range(RangeOperator::StartsWith) + ("*" | ".*", Some(VersionOperators::StrictRange(StrictRangeOperator::StartsWith))) => { + VersionOperators::StrictRange(StrictRangeOperator::StartsWith) } ("*" | ".*", Some(VersionOperators::Range(RangeOperator::GreaterEquals))) => { VersionOperators::Range(RangeOperator::GreaterEquals) @@ -155,13 +155,13 @@ fn logical_constraint_parser(input: &str) -> IResult<&str, Constraint, ParseCons VersionOperators::Range(RangeOperator::GreaterEquals) } ("*" | ".*", Some(VersionOperators::Exact(EqualityOperator::NotEquals))) => { - VersionOperators::Range(RangeOperator::NotStartsWith) + VersionOperators::StrictRange(StrictRangeOperator::NotStartsWith) } (glob @ "*" | glob @ ".*", Some(op)) => { tracing::warn!("Using {glob} with relational operator is superfluous and deprecated and will be removed in a future version of conda."); op } - ("*" | ".*", None) => VersionOperators::Range(RangeOperator::StartsWith), + ("*" | ".*", None) => VersionOperators::StrictRange(StrictRangeOperator::StartsWith), // The version string kinda looks like a regular expression. (version_remainder, _) if version_str.contains('*') || version_remainder.ends_with('$') => { @@ -184,6 +184,7 @@ fn logical_constraint_parser(input: &str) -> IResult<&str, Constraint, ParseCons match op { VersionOperators::Range(r) => Ok((rest, Constraint::Comparison(r, version))), VersionOperators::Exact(e) => Ok((rest, Constraint::Exact(e, version))), + VersionOperators::StrictRange(s) => Ok((rest, Constraint::StrictComparison(s, version))), } } @@ -230,11 +231,17 @@ mod test { ); assert_eq!( operator_parser("=3.1"), - Ok(("3.1", VersionOperators::Range(RangeOperator::StartsWith))) + Ok(( + "3.1", + VersionOperators::StrictRange(StrictRangeOperator::StartsWith) + )) ); assert_eq!( operator_parser("~=3.1"), - Ok(("3.1", VersionOperators::Range(RangeOperator::Compatible))) + Ok(( + "3.1", + VersionOperators::StrictRange(StrictRangeOperator::Compatible) + )) ); assert_eq!( @@ -295,8 +302,8 @@ mod test { logical_constraint_parser("3.1*"), Ok(( "", - Constraint::Comparison( - RangeOperator::StartsWith, + Constraint::StrictComparison( + StrictRangeOperator::StartsWith, Version::from_str("3.1").unwrap() ) )) @@ -306,8 +313,8 @@ mod test { logical_constraint_parser("3.1.*"), Ok(( "", - Constraint::Comparison( - RangeOperator::StartsWith, + Constraint::StrictComparison( + StrictRangeOperator::StartsWith, Version::from_str("3.1").unwrap() ) )) @@ -317,8 +324,8 @@ mod test { logical_constraint_parser("~=3.1"), Ok(( "", - Constraint::Comparison( - RangeOperator::Compatible, + Constraint::StrictComparison( + StrictRangeOperator::Compatible, Version::from_str("3.1").unwrap() ) )) diff --git a/crates/rattler_conda_types/src/version_spec/version_tree.rs b/crates/rattler_conda_types/src/version_spec/version_tree.rs index 98af161cd..c7bd933ba 100644 --- a/crates/rattler_conda_types/src/version_spec/version_tree.rs +++ b/crates/rattler_conda_types/src/version_spec/version_tree.rs @@ -1,4 +1,6 @@ -use crate::version_spec::{EqualityOperator, LogicalOperator, RangeOperator, VersionOperators}; +use crate::version_spec::{ + EqualityOperator, LogicalOperator, RangeOperator, StrictRangeOperator, VersionOperators, +}; use nom::{ branch::alt, bytes::complete::{tag, take_while}, @@ -34,7 +36,10 @@ fn parse_operator<'a, E: ParseError<&'a str>>( VersionOperators::Exact(EqualityOperator::NotEquals), tag("!="), ), - value(VersionOperators::Range(RangeOperator::StartsWith), tag("=")), + value( + VersionOperators::StrictRange(StrictRangeOperator::StartsWith), + tag("="), + ), value( VersionOperators::Range(RangeOperator::GreaterEquals), tag(">="), @@ -46,7 +51,7 @@ fn parse_operator<'a, E: ParseError<&'a str>>( ), value(VersionOperators::Range(RangeOperator::Less), tag("<")), value( - VersionOperators::Range(RangeOperator::Compatible), + VersionOperators::StrictRange(StrictRangeOperator::Compatible), tag("~="), ), ))(input) @@ -198,7 +203,9 @@ impl<'a> TryFrom<&'a str> for VersionTree<'a> { mod tests { use super::{parse_operator, recognize_version, LogicalOperator, VersionTree}; use crate::version_spec::version_tree::{parse_version_epoch, recognize_constraint}; - use crate::version_spec::{EqualityOperator, RangeOperator, VersionOperators}; + use crate::version_spec::{ + EqualityOperator, RangeOperator, StrictRangeOperator, VersionOperators, + }; use std::convert::TryFrom; #[test] @@ -281,11 +288,17 @@ mod tests { ); assert_eq!( parse_operator::("="), - Ok(("", VersionOperators::Range(RangeOperator::StartsWith))) + Ok(( + "", + VersionOperators::StrictRange(StrictRangeOperator::StartsWith) + )) ); assert_eq!( parse_operator::("~="), - Ok(("", VersionOperators::Range(RangeOperator::Compatible))) + Ok(( + "", + VersionOperators::StrictRange(StrictRangeOperator::Compatible) + )) ); // Anything else is an error From 85c88bd89b96720af6faa3545a5534bfd0db3b92 Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Mon, 28 Aug 2023 15:42:15 +0200 Subject: [PATCH 4/6] fix: pr changes --- .../rattler_conda_types/src/match_spec/mod.rs | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/crates/rattler_conda_types/src/match_spec/mod.rs b/crates/rattler_conda_types/src/match_spec/mod.rs index e484314ca..a0bd31bd9 100644 --- a/crates/rattler_conda_types/src/match_spec/mod.rs +++ b/crates/rattler_conda_types/src/match_spec/mod.rs @@ -112,7 +112,7 @@ use matcher::StringMatcher; /// Alternatively, an exact spec is given by `*[sha256=01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b]`. #[skip_serializing_none] #[serde_as] -#[derive(Debug, Default, Clone, Serialize, Eq, PartialEq)] +#[derive(Debug, Default, Clone, Serialize, Eq, PartialEq, Hash)] pub struct MatchSpec { /// The name of the package pub name: Option, @@ -345,21 +345,6 @@ impl MatchSpec { } } -impl Hash for MatchSpec { - fn hash(&self, state: &mut H) { - self.name.hash(state); - self.version.hash(state); - self.build.hash(state); - self.build_number.hash(state); - self.file_name.hash(state); - self.channel.hash(state); - self.subdir.hash(state); - self.namespace.hash(state); - self.md5.hash(state); - self.sha256.hash(state); - } -} - #[cfg(test)] mod tests { use std::str::FromStr; @@ -389,7 +374,6 @@ mod tests { #[test] fn test_hash_match() { - // These should not be equal as they are unequal ranges let spec1 = MatchSpec::from_str("tensorflow 2.6.*").unwrap(); let spec2 = MatchSpec::from_str("tensorflow 2.6.*").unwrap(); assert_eq!(spec1, spec2); @@ -405,7 +389,6 @@ mod tests { fn test_hash_no_match() { let spec1 = MatchSpec::from_str("tensorflow 2.6.0.*").unwrap(); let spec2 = MatchSpec::from_str("tensorflow 2.6.*").unwrap(); - dbg!(&spec1, &spec2); assert_ne!(spec1, spec2); let mut hasher = std::collections::hash_map::DefaultHasher::new(); From 17f8bffe2b6fd68213e4268ced2b1a807dd7d09e Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Mon, 28 Aug 2023 15:49:45 +0200 Subject: [PATCH 5/6] fix: clippy fixes --- .../rattler_conda_types/src/match_spec/mod.rs | 2 +- crates/rattler_conda_types/src/version/mod.rs | 8 +------- .../rattler_conda_types/src/version_spec/mod.rs | 17 ++++++++--------- crates/rattler_solve/tests/backends.rs | 8 ++++---- 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/crates/rattler_conda_types/src/match_spec/mod.rs b/crates/rattler_conda_types/src/match_spec/mod.rs index a0bd31bd9..3b9488ae2 100644 --- a/crates/rattler_conda_types/src/match_spec/mod.rs +++ b/crates/rattler_conda_types/src/match_spec/mod.rs @@ -3,7 +3,7 @@ use rattler_digest::{serde::SerializableHash, Md5Hash, Sha256Hash}; use serde::Serialize; use serde_with::{serde_as, skip_serializing_none}; use std::fmt::{Debug, Display, Formatter}; -use std::hash::{Hash, Hasher}; +use std::hash::Hash; pub mod matcher; pub mod parse; diff --git a/crates/rattler_conda_types/src/version/mod.rs b/crates/rattler_conda_types/src/version/mod.rs index 9f289e81a..401abb747 100644 --- a/crates/rattler_conda_types/src/version/mod.rs +++ b/crates/rattler_conda_types/src/version/mod.rs @@ -945,7 +945,7 @@ impl<'v> SegmentIter<'v> { /// this is not equal. Useful in ranges where we are talking /// about equality over version ranges instead of specific /// version instances -#[derive(Clone, Ord, Eq, Debug)] +#[derive(Clone, PartialOrd, Ord, Eq, Debug)] pub struct StrictVersion(pub Version); impl PartialEq for StrictVersion { @@ -957,12 +957,6 @@ impl PartialEq for StrictVersion { } } -impl PartialOrd for StrictVersion { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.0.cmp(&other.0)) - } -} - impl Display for StrictVersion { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}", self.0) diff --git a/crates/rattler_conda_types/src/version_spec/mod.rs b/crates/rattler_conda_types/src/version_spec/mod.rs index 33ba85485..a6ea5d582 100644 --- a/crates/rattler_conda_types/src/version_spec/mod.rs +++ b/crates/rattler_conda_types/src/version_spec/mod.rs @@ -228,11 +228,11 @@ impl Display for VersionSpec { StrictRangeOperator::NotStartsWith => write!(f, "!={}.*", version), op => write!(f, "{}{}", op, version), }, - VersionSpec::Range(op, version) => match op { - op => write!(f, "{}{}", op, version), + VersionSpec::Range(op, version) => { + write!(f, "{}{}", op, version) }, - VersionSpec::Exact(op, version) => match op { - op => write!(f, "{}{}", op, version), + VersionSpec::Exact(op, version) => { + write!(f, "{}{}", op, version) }, VersionSpec::Group(op, group) => { let requires_parenthesis = *op == LogicalOperator::And && part_of_or; @@ -275,10 +275,10 @@ impl VersionSpec { VersionSpec::Any => true, VersionSpec::Exact(EqualityOperator::Equals, limit) => limit == version, VersionSpec::Exact(EqualityOperator::NotEquals, limit) => limit != version, - VersionSpec::Range(RangeOperator::Greater, limit) => version > &limit, - VersionSpec::Range(RangeOperator::GreaterEquals, limit) => version >= &limit, - VersionSpec::Range(RangeOperator::Less, limit) => version < &limit, - VersionSpec::Range(RangeOperator::LessEquals, limit) => version <= &limit, + VersionSpec::Range(RangeOperator::Greater, limit) => version > limit, + VersionSpec::Range(RangeOperator::GreaterEquals, limit) => version >= limit, + VersionSpec::Range(RangeOperator::Less, limit) => version < limit, + VersionSpec::Range(RangeOperator::LessEquals, limit) => version <= limit, VersionSpec::StrictRange(StrictRangeOperator::StartsWith, limit) => { version.starts_with(&limit.0) } @@ -303,7 +303,6 @@ impl VersionSpec { #[cfg(test)] mod tests { - use crate::version::StrictVersion; use crate::version_spec::{EqualityOperator, LogicalOperator, RangeOperator}; use crate::{Version, VersionSpec}; use std::str::FromStr; diff --git a/crates/rattler_solve/tests/backends.rs b/crates/rattler_solve/tests/backends.rs index 0a0a13f64..503253d6b 100644 --- a/crates/rattler_solve/tests/backends.rs +++ b/crates/rattler_solve/tests/backends.rs @@ -423,7 +423,7 @@ mod libsolv_c { locked_packages: Vec::new(), virtual_packages: Vec::new(), available_packages: [libsolv_repodata], - specs: specs.clone(), + specs: specs, pinned_packages: Vec::new(), }) .unwrap(); @@ -486,10 +486,10 @@ fn solve( .collect(); let task = SolverTask { - locked_packages: installed_packages.clone(), - virtual_packages: virtual_packages.clone(), + locked_packages: installed_packages, + virtual_packages: virtual_packages, available_packages: [&repo_data], - specs: specs.clone(), + specs: specs, pinned_packages: Vec::new(), }; From cfda176162f11af8ffea6fab41e18802938f9e6c Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Mon, 28 Aug 2023 16:20:53 +0200 Subject: [PATCH 6/6] fix: fmt --- crates/rattler_conda_types/src/version_spec/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/rattler_conda_types/src/version_spec/mod.rs b/crates/rattler_conda_types/src/version_spec/mod.rs index a6ea5d582..246f4cf6b 100644 --- a/crates/rattler_conda_types/src/version_spec/mod.rs +++ b/crates/rattler_conda_types/src/version_spec/mod.rs @@ -230,10 +230,10 @@ impl Display for VersionSpec { }, VersionSpec::Range(op, version) => { write!(f, "{}{}", op, version) - }, + } VersionSpec::Exact(op, version) => { write!(f, "{}{}", op, version) - }, + } VersionSpec::Group(op, group) => { let requires_parenthesis = *op == LogicalOperator::And && part_of_or; if requires_parenthesis {