diff --git a/src/engine/analyzer.rs b/src/engine/analyzer.rs index 6e1067b..e593397 100644 --- a/src/engine/analyzer.rs +++ b/src/engine/analyzer.rs @@ -23,12 +23,14 @@ impl DependencyAnalyzer { dep.latest_that_matches = Some(ver.clone()); } } - if let Some(ref mut current_latest) = dep.latest { - if *current_latest < *ver { - *current_latest = ver.clone(); + if !ver.is_prerelease() { + if let Some(ref mut current_latest) = dep.latest { + if *current_latest < *ver { + *current_latest = ver.clone(); + } + } else { + dep.latest = Some(ver.clone()); } - } else { - dep.latest = Some(ver.clone()); } } @@ -50,3 +52,77 @@ impl DependencyAnalyzer { self.deps } } + +#[cfg(test)] +mod tests { + use super::{CrateDeps, CrateRelease, DependencyAnalyzer}; + + #[test] + fn tracks_latest_without_matching() { + let mut deps = CrateDeps::default(); + deps.main.insert("hyper".parse().unwrap(), "^0.11.0".parse().unwrap()); + + let mut analyzer = DependencyAnalyzer::new(&deps); + analyzer.process(vec![ + CrateRelease { name: "hyper".parse().unwrap(), version: "0.10.0".parse().unwrap(), yanked: false }, + CrateRelease { name: "hyper".parse().unwrap(), version: "0.10.1".parse().unwrap(), yanked: false } + ]); + + let analyzed = analyzer.finalize(); + + assert_eq!(analyzed.main.get("hyper").unwrap().latest_that_matches, None); + assert_eq!(analyzed.main.get("hyper").unwrap().latest, Some("0.10.1".parse().unwrap())); + } + + #[test] + fn tracks_latest_that_matches() { + let mut deps = CrateDeps::default(); + deps.main.insert("hyper".parse().unwrap(), "^0.10.0".parse().unwrap()); + + let mut analyzer = DependencyAnalyzer::new(&deps); + analyzer.process(vec![ + CrateRelease { name: "hyper".parse().unwrap(), version: "0.10.0".parse().unwrap(), yanked: false }, + CrateRelease { name: "hyper".parse().unwrap(), version: "0.10.1".parse().unwrap(), yanked: false }, + CrateRelease { name: "hyper".parse().unwrap(), version: "0.11.0".parse().unwrap(), yanked: false } + ]); + + let analyzed = analyzer.finalize(); + + assert_eq!(analyzed.main.get("hyper").unwrap().latest_that_matches, Some("0.10.1".parse().unwrap())); + assert_eq!(analyzed.main.get("hyper").unwrap().latest, Some("0.11.0".parse().unwrap())); + } + + #[test] + fn skips_yanked_releases() { + let mut deps = CrateDeps::default(); + deps.main.insert("hyper".parse().unwrap(), "^0.10.0".parse().unwrap()); + + let mut analyzer = DependencyAnalyzer::new(&deps); + analyzer.process(vec![ + CrateRelease { name: "hyper".parse().unwrap(), version: "0.10.0".parse().unwrap(), yanked: false }, + CrateRelease { name: "hyper".parse().unwrap(), version: "0.10.1".parse().unwrap(), yanked: true }, + ]); + + let analyzed = analyzer.finalize(); + + assert_eq!(analyzed.main.get("hyper").unwrap().latest_that_matches, Some("0.10.0".parse().unwrap())); + assert_eq!(analyzed.main.get("hyper").unwrap().latest, Some("0.10.0".parse().unwrap())); + } + + #[test] + fn skips_prereleases() { + let mut deps = CrateDeps::default(); + deps.main.insert("hyper".parse().unwrap(), "^0.10.0".parse().unwrap()); + + let mut analyzer = DependencyAnalyzer::new(&deps); + analyzer.process(vec![ + CrateRelease { name: "hyper".parse().unwrap(), version: "0.10.0".parse().unwrap(), yanked: false }, + CrateRelease { name: "hyper".parse().unwrap(), version: "0.10.1-alpha".parse().unwrap(), yanked: false }, + ]); + + let analyzed = analyzer.finalize(); + + assert_eq!(analyzed.main.get("hyper").unwrap().latest_that_matches, Some("0.10.0".parse().unwrap())); + assert_eq!(analyzed.main.get("hyper").unwrap().latest, Some("0.10.0".parse().unwrap())); + } +} diff --git a/src/models/crates.rs b/src/models/crates.rs index 7b5a1b9..a93538f 100644 --- a/src/models/crates.rs +++ b/src/models/crates.rs @@ -1,3 +1,4 @@ +use std::borrow::Borrow; use std::collections::BTreeMap; use std::str::FromStr; @@ -12,8 +13,11 @@ impl Into for CrateName { } } -#[derive(Debug)] -pub struct CrateNameValidationError; +impl Borrow for CrateName { + fn borrow(&self) -> &str { + &self.0 + } +} impl AsRef for CrateName { fn as_ref(&self) -> &str { @@ -21,6 +25,9 @@ impl AsRef for CrateName { } } +#[derive(Debug)] +pub struct CrateNameValidationError; + impl FromStr for CrateName { type Err = CrateNameValidationError; @@ -44,7 +51,7 @@ pub struct CrateRelease { pub yanked: bool } -#[derive(Debug)] +#[derive(Debug, Default)] pub struct CrateDeps { pub main: BTreeMap, pub dev: BTreeMap,