diff --git a/src/cargo/core/dependency.rs b/src/cargo/core/dependency.rs index 3e4b7c75c23..fcffed66d3d 100644 --- a/src/cargo/core/dependency.rs +++ b/src/cargo/core/dependency.rs @@ -1,38 +1,55 @@ -use core::NameVer; +use semver::Version; +use core::{NameVer,VersionReq}; +use util::CargoResult; -#[deriving(Eq,Clone,Show,Encodable,Decodable)] +#[deriving(Eq,Clone,Show)] pub struct Dependency { - name: NameVer + name: ~str, + req: VersionReq } impl Dependency { - pub fn new(name: &str) -> Dependency { - Dependency { name: NameVer::new(name.to_owned(), "1.0.0") } + pub fn new(name: &str, req: &VersionReq) -> Dependency { + Dependency { + name: name.to_owned(), + req: req.clone() + } } - pub fn with_namever(name: &NameVer) -> Dependency { - Dependency { name: name.clone() } + pub fn parse(name: &str, version: &str) -> CargoResult { + Ok(Dependency { + name: name.to_owned(), + req: try!(VersionReq::parse(version)) + }) } - pub fn with_name_and_version(name: &str, version: &str) -> Dependency { - Dependency { name: NameVer::new(name, version) } + pub fn exact(name: &str, version: &Version) -> Dependency { + Dependency { + name: name.to_owned(), + req: VersionReq::exact(version) + } } - pub fn get_namever<'a>(&'a self) -> &'a NameVer { - &self.name + pub fn get_version_req<'a>(&'a self) -> &'a VersionReq { + &self.req } pub fn get_name<'a>(&'a self) -> &'a str { - self.name.get_name() + self.name.as_slice() } } -pub trait DependencyNameVers { - fn namevers(&self) -> Vec; +#[deriving(Eq,Clone,Encodable)] +pub struct SerializedDependency { + name: ~str, + req: ~str } -impl DependencyNameVers for Vec { - fn namevers(&self) -> Vec { - self.iter().map(|dep| dep.get_namever().clone()).collect() +impl SerializedDependency { + pub fn from_dependency(dep: &Dependency) -> SerializedDependency { + SerializedDependency { + name: dep.get_name().to_owned(), + req: dep.get_version_req().to_str() + } } } diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index 1bdd71d648b..159483fc202 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -1,6 +1,7 @@ use std::fmt; use std::fmt::{Show,Formatter}; use collections::HashMap; +use semver::Version; use serialize::{Encoder,Encodable}; use core::{ Dependency, @@ -8,6 +9,8 @@ use core::{ Package, Summary }; +use core::dependency::SerializedDependency; +use util::CargoResult; #[deriving(Eq,Clone)] pub struct Manifest { @@ -25,7 +28,9 @@ impl Show for Manifest { #[deriving(Eq,Clone,Encodable)] pub struct SerializedManifest { - summary: Summary, + name: ~str, + version: ~str, + dependencies: Vec, authors: Vec<~str>, targets: Vec, target_dir: ~str @@ -34,7 +39,9 @@ pub struct SerializedManifest { impl> Encodable for Manifest { fn encode(&self, s: &mut S) -> Result<(), E> { SerializedManifest { - summary: self.summary.clone(), + name: self.summary.get_name().to_owned(), + version: self.summary.get_version().to_str(), + dependencies: self.summary.get_dependencies().iter().map(|d| SerializedDependency::from_dependency(d)).collect(), authors: self.authors.clone(), targets: self.targets.clone(), target_dir: self.target_dir.as_str().unwrap().to_owned() @@ -101,6 +108,10 @@ impl Manifest { self.get_summary().get_name_ver().get_name() } + pub fn get_version<'a>(&'a self) -> &'a Version { + self.get_summary().get_name_ver().get_version() + } + pub fn get_authors<'a>(&'a self) -> &'a [~str] { self.authors.as_slice() } @@ -176,30 +187,34 @@ pub struct TomlManifest { } impl TomlManifest { - pub fn to_package(&self, path: &str) -> Package { + pub fn to_package(&self, path: &str) -> CargoResult { // TODO: Convert hte argument to take a Path let path = Path::new(path); // Get targets let targets = normalize(&self.lib, &self.bin); - // Get deps - let deps = self.dependencies.clone().map(|deps| { - deps.iter().map(|(k,v)| { - // This can produce an invalid version, but it's temporary because this needs - // to be replaced with Dependency, not NameVer - Dependency::with_namever(&NameVer::new(k.clone(), v.clone())) - }).collect() - }).unwrap_or_else(|| vec!()); + + let mut deps = Vec::new(); + + // Collect the deps + match self.dependencies { + Some(ref dependencies) => { + for (n, v) in dependencies.iter() { + deps.push(try!(Dependency::parse(*n, *v))); + } + } + None => () + } // TODO: https://github.com/mozilla/rust/issues/14049 let root = Path::new(path.dirname()); - Package::new( + Ok(Package::new( &Manifest::new( &Summary::new(&self.project.to_name_ver(), deps.as_slice()), targets.as_slice(), &Path::new("target")), - &root) + &root)) } } diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index a208517f6a9..4e1834679b9 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -9,6 +9,7 @@ use core::{ Target, Summary }; +use core::dependency::SerializedDependency; use util::graph; use serialize::{Encoder,Encodable}; @@ -24,7 +25,7 @@ pub struct Package { struct SerializedPackage { name: ~str, version: ~str, - dependencies: Vec, + dependencies: Vec, authors: Vec<~str>, targets: Vec, root: ~str @@ -39,7 +40,7 @@ impl> Encodable for Package { SerializedPackage { name: name_ver.get_name().to_owned(), version: name_ver.get_version().to_str(), - dependencies: Vec::from_slice(summary.get_dependencies()), + dependencies: summary.get_dependencies().iter().map(|d| SerializedDependency::from_dependency(d)).collect(), authors: Vec::from_slice(manifest.get_authors()), targets: Vec::from_slice(manifest.get_targets()), root: self.root.as_str().unwrap().to_owned() @@ -56,7 +57,7 @@ impl Package { } pub fn to_dependency(&self) -> Dependency { - Dependency::with_namever(self.manifest.get_summary().get_name_ver()) + Dependency::exact(self.manifest.get_name(), self.manifest.get_version()) } pub fn get_manifest<'a>(&'a self) -> &'a Manifest { diff --git a/src/cargo/core/resolver.rs b/src/cargo/core/resolver.rs index 7e4a747d2a4..6523913c968 100644 --- a/src/cargo/core/resolver.rs +++ b/src/cargo/core/resolver.rs @@ -62,7 +62,7 @@ mod test { macro_rules! pkg( ($name:expr => $($deps:expr),+) => ( { - let d: Vec = vec!($($deps),+).iter().map(|s| Dependency::new(*s)).collect(); + let d: Vec = vec!($($deps),+).iter().map(|s| Dependency::parse(*s, "1.0.0").unwrap()).collect(); Summary::new(&NameVer::new($name, "1.0.0"), d.as_slice()) } ); @@ -77,7 +77,7 @@ mod test { } fn dep(name: &str) -> Dependency { - Dependency::new(name) + Dependency::parse(name, "1.0.0").unwrap() } fn registry(pkgs: Vec) -> Vec { diff --git a/src/cargo/core/summary.rs b/src/cargo/core/summary.rs index dd85444284b..78059427c0c 100644 --- a/src/cargo/core/summary.rs +++ b/src/cargo/core/summary.rs @@ -1,9 +1,10 @@ +use semver::Version; use core::{ Dependency, NameVer }; -#[deriving(Show,Clone,Eq,Encodable)] +#[deriving(Show,Clone,Eq)] pub struct Summary { name_ver: NameVer, dependencies: Vec @@ -25,6 +26,10 @@ impl Summary { self.get_name_ver().get_name() } + pub fn get_version<'a>(&'a self) -> &'a Version { + self.get_name_ver().get_version() + } + pub fn get_dependencies<'a>(&'a self) -> &'a [Dependency] { self.dependencies.as_slice() } @@ -43,6 +48,6 @@ impl SummaryVec for Vec { // TODO: Delete fn deps(&self) -> Vec { - self.iter().map(|summary| Dependency::with_namever(summary.get_name_ver())).collect() + self.iter().map(|summary| Dependency::exact(summary.get_name(), summary.get_version())).collect() } } diff --git a/src/cargo/core/version_req.rs b/src/cargo/core/version_req.rs index 8d984da972b..11739a0c54c 100644 --- a/src/cargo/core/version_req.rs +++ b/src/cargo/core/version_req.rs @@ -6,11 +6,12 @@ use std::str::CharOffsets; use semver::Version; use util::{other_error,CargoResult}; +#[deriving(Eq,Clone)] pub struct VersionReq { predicates: Vec } -#[deriving(Eq)] +#[deriving(Eq,Clone)] enum Op { Ex, // Exact Gt, // Greater than @@ -19,6 +20,7 @@ enum Op { LtEq // Less than or equal to } +#[deriving(Eq,Clone)] struct Predicate { op: Op, major: uint, @@ -58,12 +60,25 @@ impl VersionReq { Ok(VersionReq { predicates: predicates }) } + pub fn exact(version: &Version) -> VersionReq { + VersionReq { predicates: vec!(Predicate::exact(version)) } + } + pub fn matches(&self, version: &Version) -> bool { self.predicates.iter().all(|p| p.matches(version)) } } impl Predicate { + pub fn exact(version: &Version) -> Predicate { + Predicate { + op: Ex, + major: version.major, + minor: Some(version.minor), + patch: Some(version.patch) + } + } + pub fn matches(&self, ver: &Version) -> bool { match self.op { Ex => self.is_exact(ver), diff --git a/src/cargo/ops/cargo_read_manifest.rs b/src/cargo/ops/cargo_read_manifest.rs index 1bb26cdf9d4..0fae527c132 100644 --- a/src/cargo/ops/cargo_read_manifest.rs +++ b/src/cargo/ops/cargo_read_manifest.rs @@ -11,7 +11,7 @@ pub fn read_manifest(path: &str) -> CargoResult { let toml = try!(load_toml(root).map_err(|err: CargoError| human_error(format!("Cargo.toml is not a valid Cargo manifest"), format!("path={}", path), err))); - Ok(toml.to_package(path)) + toml.to_package(path) } fn parse_from_file(path: &str) -> CargoResult {