diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2020-10-13 20:42:39 +0200 |
---|---|---|
committer | Matthias Beyer <mail@beyermatthias.de> | 2020-10-13 20:54:46 +0200 |
commit | c6c68d823e90ea0323e0fc39cd2621afe63a511f (patch) | |
tree | 5be56008dad5062bcaeff5966849237ce8793f6d | |
parent | 904f0bbebe7661a801414317aa2b6faf82752dd9 (diff) |
Implement version / constraint parsing
-rw-r--r-- | Cargo.toml | 28 | ||||
-rw-r--r-- | examples/packages/example_1/pkgA/pkg.toml | 2 | ||||
-rw-r--r-- | src/package/dependency.rs | 77 | ||||
-rw-r--r-- | src/package/version.rs | 96 |
4 files changed, 184 insertions, 19 deletions
@@ -7,19 +7,21 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -log = "0.3" -tracing = "0.1" -toml = "0.5" -serde = "1" -config = "0.9" -anyhow = "1" -getset = "0.1" -walkdir = "2" -resiter = "0.4" -itertools = "0.9" -clap-v3 = "3.0.0-beta.1" -indicatif = "0.15" -env_logger = "0.7" +log = "0.3" +tracing = "0.1" +toml = "0.5" +serde = "1" +config = "0.9" +anyhow = "1" +getset = "0.1" +walkdir = "2" +resiter = "0.4" +itertools = "0.9" +clap-v3 = "3.0.0-beta.1" +indicatif = "0.15" +env_logger = "0.7" +regex = "1" +lazy_static = "1.4" url = { version = "2", features = ["serde"] } tokio = { version = "0.2", features = ["full"] } diff --git a/examples/packages/example_1/pkgA/pkg.toml b/examples/packages/example_1/pkgA/pkg.toml index 056a0f7..4d9d0bf 100644 --- a/examples/packages/example_1/pkgA/pkg.toml +++ b/examples/packages/example_1/pkgA/pkg.toml @@ -2,7 +2,7 @@ name = "pkgA" version = "1.0.0" [dependencies] -runtime = [ "pkgB-1.0.0" ] +runtime = [ "pkgB =1.0.0" ] [source] url = "http://somerandomthi.ng/foo/bar.tar.gz" diff --git a/src/package/dependency.rs b/src/package/dependency.rs index da3ac3a..14146c3 100644 --- a/src/package/dependency.rs +++ b/src/package/dependency.rs @@ -1,5 +1,8 @@ use std::result::Result as RResult; use serde::Deserialize; +use regex::Regex; +use lazy_static::lazy_static; +use anyhow::anyhow; use crate::package::PackageName; use crate::package::PackageVersionConstraint; @@ -17,13 +20,81 @@ pub struct BuildDependency(String); #[serde(transparent)] pub struct Dependency(String); +impl From<String> for Dependency { + fn from(s: String) -> Dependency { + Dependency(s) + } +} + impl std::convert::TryInto<(PackageName, PackageVersionConstraint)> for Dependency { type Error = anyhow::Error; fn try_into(self) -> RResult<(PackageName, PackageVersionConstraint), Self::Error> { - // TODO: Implement properly - let v: Vec<_> = self.0.split("-").collect(); - Ok((PackageName::from(String::from(v[0])), PackageVersionConstraint::Any)) + lazy_static! { + static ref RE: Regex = Regex::new("^(?P<name>[[:alpha:]]([[[:alnum:]]-_])*) (?P<version>([\\*=><])?[[:alnum:]]([[[:alnum:]][[:punct:]]])*)$").unwrap(); + } + + let caps = RE.captures(&self.0) + .ok_or_else(|| anyhow!("Could not parse into package name and package version constraint: '{}'", self.0))?; + + let name = caps.name("name") + .ok_or_else(|| anyhow!("Could not parse name: '{}'", self.0))?; + + let vers = caps.name("version") + .ok_or_else(|| anyhow!("Could not parse version: '{}'", self.0))?; + + let constraint = PackageVersionConstraint::parse(vers.as_str())?; + + Ok((PackageName::from(String::from(name.as_str())), constraint)) } } +#[cfg(test)] +mod tests { + use super::*; + use std::convert::TryInto; + use crate::package::PackageVersion; + use crate::package::PackageVersionConstraint; + + // + // helper functions + // + + fn name(s: &'static str) -> PackageName { + PackageName::from(String::from(s)) + } + + fn exact(s: &'static str) -> PackageVersionConstraint { + PackageVersionConstraint::Exact(PackageVersion::from(String::from(s))) + } + + fn higher_as(s: &'static str) -> PackageVersionConstraint { + PackageVersionConstraint::HigherAs(PackageVersion::from(String::from(s))) + } + + // + // tests + // + + #[test] + fn test_dependency_conversion_1() { + let s = "vim =8.2"; + let d = Dependency::from(String::from(s)); + + let (n, c) = d.try_into().unwrap(); + + assert_eq!(n, name("vim")); + assert_eq!(c, exact("8.2")); + } + + #[test] + fn test_dependency_conversion_2() { + let s = "gtk15 >1b"; + let d = Dependency::from(String::from(s)); + + let (n, c) = d.try_into().unwrap(); + + assert_eq!(n, name("gtk15")); + assert_eq!(c, higher_as("1b")); + } +} diff --git a/src/package/version.rs b/src/package/version.rs index d6c385d..b326017 100644 --- a/src/package/version.rs +++ b/src/package/version.rs @@ -1,4 +1,5 @@ use serde::Deserialize; +use anyhow::anyhow; use anyhow::Result; #[derive(Deserialize, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)] @@ -17,7 +18,6 @@ impl From<String> for PackageVersion { #[allow(unused)] pub enum PackageVersionConstraint { Any, - Latest, LowerAs(PackageVersion), HigherAs(PackageVersion), InRange(PackageVersion, PackageVersion), @@ -28,13 +28,50 @@ impl PackageVersionConstraint { pub fn matches(&self, v: &PackageVersion) -> Result<PackageVersionMatch> { match self { PackageVersionConstraint::Any => Ok(PackageVersionMatch::True), - PackageVersionConstraint::Latest => Ok(PackageVersionMatch::Undecided), PackageVersionConstraint::LowerAs(_vers) => Ok(PackageVersionMatch::Undecided), // TODO: Fix implementation PackageVersionConstraint::HigherAs(_vers) => Ok(PackageVersionMatch::Undecided), // TODO: Fix implementation PackageVersionConstraint::InRange(_vers1, _vers2) => Ok(PackageVersionMatch::Undecided), // TODO: Fix implementation PackageVersionConstraint::Exact(vers) => Ok(PackageVersionMatch::from(*v == *vers)), } } + + // TODO: Make this nice? + pub fn parse(s: &str) -> Result<Self> { + if s.is_empty() { + return Err(anyhow!("Cannot parse: '{}'", s)) + } + + let first_char = s.chars().next().ok_or_else(|| anyhow!("Failed to find first character: '{}'", s))?; + if first_char == '*' { + return Ok(PackageVersionConstraint::Any) + } + + let v = s.chars().skip(1).collect::<String>(); + + if v.is_empty() { + return Err(anyhow!("Not a version: '{}'", v)) + } + + if first_char == '=' { + Ok(PackageVersionConstraint::Exact(PackageVersion::from(v))) + } else if first_char == '>' { + Ok(PackageVersionConstraint::HigherAs(PackageVersion::from(v))) + } else if first_char == '<' { + Ok(PackageVersionConstraint::LowerAs(PackageVersion::from(v))) + } else { + let mut iter = s.split(".."); + + let a = iter.next() + .map(String::from) + .ok_or_else(|| anyhow!("Trying to parse version range constraint failed: '{}'", s))?; + + let b = iter.next() + .map(String::from) + .ok_or_else(|| anyhow!("Trying to parse version range constraint failed: '{}'", s))?; + + Ok(PackageVersionConstraint::InRange(PackageVersion::from(a), PackageVersion::from(b))) + } + } } #[derive(Debug, Clone, Copy, Eq, PartialEq)] @@ -72,3 +109,58 @@ impl From<bool> for PackageVersionMatch { } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse_version_constraint_1() { + let s = "*"; + let c = PackageVersionConstraint::parse(s).unwrap(); + assert_eq!(c, PackageVersionConstraint::Any); + } + + #[test] + fn test_parse_version_constraint_2() { + let s = "=1"; + let c = PackageVersionConstraint::parse(s).unwrap(); + assert_eq!(c, PackageVersionConstraint::Exact(PackageVersion::from(String::from("1")))); + } + + #[test] + fn test_parse_version_constraint_3() { + let s = ">1"; + let c = PackageVersionConstraint::parse(s).unwrap(); + assert_eq!(c, PackageVersionConstraint::HigherAs(PackageVersion::from(String::from("1")))); + } + + #[test] + fn test_parse_version_constraint_4() { + let s = "<1"; + let c = PackageVersionConstraint::parse(s).unwrap(); + assert_eq!(c, PackageVersionConstraint::LowerAs(PackageVersion::from(String::from("1")))); + } + + #[test] + fn test_parse_version_constraint_5() { + let s = "=1.0.17"; + let c = PackageVersionConstraint::parse(s).unwrap(); + assert_eq!(c, PackageVersionConstraint::Exact(PackageVersion::from(String::from("1.0.17")))); + } + + #[test] + fn test_parse_version_constraint_6() { + let s = "=1.0.17asejg"; + let c = PackageVersionConstraint::parse(s).unwrap(); + assert_eq!(c, PackageVersionConstraint::Exact(PackageVersion::from(String::from("1.0.17asejg")))); + } + + #[test] + fn test_parse_version_constraint_7() { + let s = "=1-0B17-beta1247_commit_12653hasd"; + let c = PackageVersionConstraint::parse(s).unwrap(); + assert_eq!(c, PackageVersionConstraint::Exact(PackageVersion::from(String::from("1-0B17-beta1247_commit_12653hasd")))); + } +} + |