2018-01-26 12:15:53 +00:00
|
|
|
use std::collections::BTreeMap;
|
2018-01-26 03:37:46 +00:00
|
|
|
use std::str::FromStr;
|
|
|
|
|
2018-01-26 12:15:53 +00:00
|
|
|
use semver::{Version, VersionReq};
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
2018-01-26 03:37:46 +00:00
|
|
|
pub struct CrateName(String);
|
|
|
|
|
2018-01-26 12:15:53 +00:00
|
|
|
impl Into<String> for CrateName {
|
|
|
|
fn into(self) -> String {
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-26 03:37:46 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct CrateNameValidationError;
|
|
|
|
|
|
|
|
impl AsRef<str> for CrateName {
|
2018-01-26 12:15:53 +00:00
|
|
|
fn as_ref(&self) -> &str {
|
|
|
|
self.0.as_ref()
|
|
|
|
}
|
2018-01-26 03:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl FromStr for CrateName {
|
|
|
|
type Err = CrateNameValidationError;
|
|
|
|
|
|
|
|
fn from_str(input: &str) -> Result<CrateName, CrateNameValidationError> {
|
|
|
|
let is_valid = input.chars().all(|c| {
|
|
|
|
c.is_ascii_alphanumeric() || c == '_' || c == '-'
|
|
|
|
});
|
|
|
|
|
|
|
|
if !is_valid {
|
|
|
|
Err(CrateNameValidationError)
|
|
|
|
} else {
|
|
|
|
Ok(CrateName(input.to_string()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-01-26 12:15:53 +00:00
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct CrateRelease {
|
|
|
|
pub name: CrateName,
|
|
|
|
pub version: Version,
|
|
|
|
pub yanked: bool
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct CrateDeps {
|
|
|
|
pub main: BTreeMap<CrateName, VersionReq>,
|
|
|
|
pub dev: BTreeMap<CrateName, VersionReq>,
|
|
|
|
pub build: BTreeMap<CrateName, VersionReq>
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct AnalyzedDependency {
|
|
|
|
pub required: VersionReq,
|
|
|
|
pub latest_that_matches: Option<Version>,
|
|
|
|
pub latest: Option<Version>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AnalyzedDependency {
|
|
|
|
pub fn new(required: VersionReq) -> AnalyzedDependency {
|
|
|
|
AnalyzedDependency {
|
|
|
|
required,
|
|
|
|
latest_that_matches: None,
|
|
|
|
latest: None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_outdated(&self) -> bool {
|
|
|
|
self.latest > self.latest_that_matches
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct AnalyzedDependencies {
|
|
|
|
pub main: BTreeMap<CrateName, AnalyzedDependency>,
|
|
|
|
pub dev: BTreeMap<CrateName, AnalyzedDependency>,
|
|
|
|
pub build: BTreeMap<CrateName, AnalyzedDependency>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AnalyzedDependencies {
|
|
|
|
pub fn new(deps: &CrateDeps) -> AnalyzedDependencies {
|
|
|
|
let main = deps.main.iter().map(|(name, req)| {
|
|
|
|
(name.clone(), AnalyzedDependency::new(req.clone()))
|
|
|
|
}).collect();
|
|
|
|
let dev = deps.dev.iter().map(|(name, req)| {
|
|
|
|
(name.clone(), AnalyzedDependency::new(req.clone()))
|
|
|
|
}).collect();
|
|
|
|
let build = deps.build.iter().map(|(name, req)| {
|
|
|
|
(name.clone(), AnalyzedDependency::new(req.clone()))
|
|
|
|
}).collect();
|
|
|
|
AnalyzedDependencies { main, dev, build }
|
|
|
|
}
|
2018-01-27 01:40:17 +00:00
|
|
|
|
|
|
|
pub fn any_outdated(&self) -> bool {
|
|
|
|
let main_any_outdated = self.main.iter()
|
|
|
|
.any(|(_, dep)| dep.is_outdated());
|
|
|
|
let dev_any_outdated = self.dev.iter()
|
|
|
|
.any(|(_, dep)| dep.is_outdated());
|
|
|
|
let build_any_outdated = self.build.iter()
|
|
|
|
.any(|(_, dep)| dep.is_outdated());
|
|
|
|
main_any_outdated || dev_any_outdated || build_any_outdated
|
|
|
|
}
|
2018-01-26 12:15:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum CrateManifest {
|
2018-01-27 01:17:50 +00:00
|
|
|
Crate(CrateName, CrateDeps)
|
2018-01-26 12:15:53 +00:00
|
|
|
}
|