You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
5.1 KiB
167 lines
5.1 KiB
use crate::version::Version; |
|
use std::str::FromStr; |
|
|
|
#[derive(Clone, Debug)] |
|
pub enum UserVersion { |
|
OnlyMajor(u64), |
|
MajorMinor(u64, u64), |
|
Full(Version), |
|
} |
|
|
|
impl UserVersion { |
|
pub fn to_version<'a, T>( |
|
&self, |
|
available_versions: T, |
|
config: &crate::config::FnmConfig, |
|
) -> Option<&'a Version> |
|
where |
|
T: IntoIterator<Item = &'a Version>, |
|
{ |
|
available_versions |
|
.into_iter() |
|
.filter(|x| self.matches(x, config)) |
|
.max() |
|
} |
|
|
|
pub fn alias_name(&self) -> Option<String> { |
|
match self { |
|
Self::Full(version) => version.alias_name(), |
|
_ => None, |
|
} |
|
} |
|
|
|
pub fn matches(&self, version: &Version, config: &crate::config::FnmConfig) -> bool { |
|
match (self, version) { |
|
(Self::Full(a), b) if a == b => true, |
|
(Self::Full(user_version), maybe_alias) => { |
|
match (user_version.alias_name(), maybe_alias.find_aliases(config)) { |
|
(None, _) | (_, Err(_)) => false, |
|
(Some(user_alias), Ok(aliases)) => { |
|
aliases.iter().any(|alias| alias.name() == user_alias) |
|
} |
|
} |
|
} |
|
(_, Version::Bypassed | Version::Lts(_) | Version::Alias(_)) => false, |
|
(Self::OnlyMajor(major), Version::Semver(other)) => *major == other.major, |
|
(Self::MajorMinor(major, minor), Version::Semver(other)) => { |
|
*major == other.major && *minor == other.minor |
|
} |
|
} |
|
} |
|
} |
|
|
|
fn next_of<'a, T: FromStr, It: Iterator<Item = &'a str>>(i: &mut It) -> Option<T> { |
|
let x = i.next()?; |
|
T::from_str(x).ok() |
|
} |
|
|
|
impl std::fmt::Display for UserVersion { |
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
|
match self { |
|
Self::Full(x) => x.fmt(f), |
|
Self::OnlyMajor(major) => write!(f, "v{}.x.x", major), |
|
Self::MajorMinor(major, minor) => write!(f, "v{}.{}.x", major, minor), |
|
} |
|
} |
|
} |
|
|
|
fn skip_first_v(str: &str) -> &str { |
|
str.strip_prefix('v').unwrap_or(str) |
|
} |
|
|
|
impl FromStr for UserVersion { |
|
type Err = semver::Error; |
|
fn from_str(s: &str) -> Result<UserVersion, Self::Err> { |
|
match Version::parse(s) { |
|
Ok(v) => Ok(Self::Full(v)), |
|
Err(e) => { |
|
let mut parts = skip_first_v(s.trim()).split('.'); |
|
match (next_of::<u64, _>(&mut parts), next_of::<u64, _>(&mut parts)) { |
|
(Some(major), None) => Ok(Self::OnlyMajor(major)), |
|
(Some(major), Some(minor)) => Ok(Self::MajorMinor(major, minor)), |
|
_ => Err(e), |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
#[cfg(test)] |
|
impl PartialEq for UserVersion { |
|
fn eq(&self, other: &Self) -> bool { |
|
match (self, other) { |
|
(Self::OnlyMajor(a), Self::OnlyMajor(b)) if a == b => true, |
|
(Self::MajorMinor(a1, a2), Self::MajorMinor(b1, b2)) if (a1, a2) == (b1, b2) => true, |
|
(Self::Full(v1), Self::Full(v2)) if v1 == v2 => true, |
|
(_, _) => false, |
|
} |
|
} |
|
} |
|
|
|
#[cfg(test)] |
|
mod tests { |
|
use crate::config::FnmConfig; |
|
|
|
use super::*; |
|
|
|
#[test] |
|
fn test_parsing_only_major() { |
|
let version = UserVersion::from_str("10").ok(); |
|
assert_eq!(version, Some(UserVersion::OnlyMajor(10))); |
|
} |
|
|
|
#[test] |
|
fn test_parsing_major_minor() { |
|
let version = UserVersion::from_str("10.20").ok(); |
|
assert_eq!(version, Some(UserVersion::MajorMinor(10, 20))); |
|
} |
|
|
|
#[test] |
|
fn test_parsing_only_major_with_v() { |
|
let version = UserVersion::from_str("v10").ok(); |
|
assert_eq!(version, Some(UserVersion::OnlyMajor(10))); |
|
} |
|
|
|
#[test] |
|
fn test_major_to_version() { |
|
let expected = Version::parse("6.1.0").unwrap(); |
|
let versions = vec![ |
|
Version::parse("6.0.0").unwrap(), |
|
Version::parse("6.0.1").unwrap(), |
|
expected.clone(), |
|
Version::parse("7.0.1").unwrap(), |
|
]; |
|
let result = UserVersion::OnlyMajor(6).to_version(&versions, &FnmConfig::default()); |
|
|
|
assert_eq!(result, Some(&expected)); |
|
} |
|
|
|
#[test] |
|
fn test_major_minor_to_version() { |
|
let expected = Version::parse("6.0.1").unwrap(); |
|
let versions = vec![ |
|
Version::parse("6.0.0").unwrap(), |
|
Version::parse("6.1.0").unwrap(), |
|
expected.clone(), |
|
Version::parse("7.0.1").unwrap(), |
|
]; |
|
let result = UserVersion::MajorMinor(6, 0).to_version(&versions, &FnmConfig::default()); |
|
|
|
assert_eq!(result, Some(&expected)); |
|
} |
|
|
|
#[test] |
|
fn test_semver_to_version() { |
|
let expected = Version::parse("6.0.0").unwrap(); |
|
let versions = vec![ |
|
expected.clone(), |
|
Version::parse("6.1.0").unwrap(), |
|
Version::parse("6.0.1").unwrap(), |
|
Version::parse("7.0.1").unwrap(), |
|
]; |
|
let result = |
|
UserVersion::Full(expected.clone()).to_version(&versions, &FnmConfig::default()); |
|
|
|
assert_eq!(result, Some(&expected)); |
|
} |
|
}
|
|
|