WIP3
authorYehuda Katz + Carl Lerche <engineering@tilde.io>
Tue, 17 Jun 2014 01:16:34 +0000 (18:16 -0700)
committerTim Carey-Smith <tim@spork.in>
Tue, 17 Jun 2014 01:16:34 +0000 (18:16 -0700)
src/cargo/core/dependency.rs
src/cargo/core/mod.rs
src/cargo/core/package.rs
src/cargo/core/registry.rs
src/cargo/core/resolver.rs
src/cargo/core/source.rs
src/cargo/core/summary.rs
src/cargo/ops/cargo_compile.rs
src/cargo/util/toml.rs

index 836c962dd3d5e210e984933737f8de8bcf05ebd7..ab1629819f4ad2857f62e21268491502e40e4161 100644 (file)
@@ -1,31 +1,35 @@
 use semver::Version;
-use core::{VersionReq};
+use core::{VersionReq,SourceId};
 use util::CargoResult;
 
 #[deriving(PartialEq,Clone,Show)]
 pub struct Dependency {
     name: String,
+    namespace: SourceId,
     req: VersionReq
 }
 
 impl Dependency {
-    pub fn new(name: &str, req: &VersionReq) -> Dependency {
+    pub fn new(name: &str, req: &VersionReq, namespace: &SourceId) -> Dependency {
         Dependency {
             name: name.to_str(),
+            namespace: namespace.clone(),
             req: req.clone()
         }
     }
 
-    pub fn parse(name: &str, version: &str) -> CargoResult<Dependency> {
+    pub fn parse(name: &str, version: &str, namespace: &SourceId) -> CargoResult<Dependency> {
         Ok(Dependency {
             name: name.to_str(),
-            req: try!(VersionReq::parse(version))
+            namespace: namespace.clone(),
+            req: try!(VersionReq::parse(version)),
         })
     }
 
-    pub fn exact(name: &str, version: &Version) -> Dependency {
+    pub fn exact(name: &str, version: &Version, namespace: &SourceId) -> Dependency {
         Dependency {
             name: name.to_str(),
+            namespace: namespace.clone(),
             req: VersionReq::exact(version)
         }
     }
@@ -37,6 +41,10 @@ impl Dependency {
     pub fn get_name<'a>(&'a self) -> &'a str {
         self.name.as_slice()
     }
+
+    pub fn get_namespace<'a>(&'a self) -> &'a SourceId {
+        &self.namespace
+    }
 }
 
 #[deriving(PartialEq,Clone,Encodable)]
index 781d200871ceff1d0335c2012359179b43efa7c2..9d041299e0cf850bbad4ab286545d384f4124484 100644 (file)
@@ -19,7 +19,11 @@ pub use self::package_id::{
 
 pub use self::source::{
     Source,
-    SourceSet
+    SourceId,
+    SourceSet,
+    GitKind,
+    PathKind,
+    RegistryKind
 };
 
 pub use self::summary::{
@@ -38,5 +42,5 @@ pub mod manifest;
 pub mod resolver;
 pub mod summary;
 pub mod shell;
-mod registry;
+pub mod registry;
 mod version_req;
index 6cd9562a1438ef87a44e3150295add2bdd68cfcf..da9c13eac71f988e93b0d83ac5382bfe6b7978dc 100644 (file)
@@ -12,7 +12,7 @@ use core::{
     Summary
 };
 use core::dependency::SerializedDependency;
-use util::graph;
+use util::{CargoResult, graph};
 use serialize::{Encoder,Encodable};
 use core::source::SourceId;
 
@@ -59,10 +59,6 @@ impl Package {
         }
     }
 
-    pub fn to_dependency(&self) -> Dependency {
-        Dependency::exact(self.manifest.get_name(), self.manifest.get_version())
-    }
-
     pub fn get_manifest<'a>(&'a self) -> &'a Manifest {
         &self.manifest
     }
@@ -120,7 +116,7 @@ impl Show for Package {
 
 #[deriving(PartialEq,Clone,Show)]
 pub struct PackageSet {
-    packages: Vec<Package>
+    packages: Vec<Package>,
 }
 
 impl PackageSet {
@@ -178,10 +174,10 @@ impl PackageSet {
 }
 
 impl Registry for PackageSet {
-  fn query<'a>(&'a self, name: &str) -> Vec<&'a Summary> {
-    self.packages.iter()
-      .filter(|pkg| name == pkg.get_name())
-      .map(|pkg| pkg.get_summary())
-      .collect()
-  }
+    fn query(&mut self, name: &Dependency) -> CargoResult<Vec<Summary>> {
+        Ok(self.packages.iter()
+            .filter(|pkg| name.get_name() == pkg.get_name())
+            .map(|pkg| pkg.get_summary().clone())
+            .collect())
+    }
 }
index 2aeeca19d569e44fd932833e9cb9bdb2f23237a3..91b8ea5259f6947d3525185a55f210beda2bf3ad 100644 (file)
@@ -1,17 +1,72 @@
 use std::vec::Vec;
-
-use core::{
-    Summary
-};
+use core::{Source, SourceId, SourceSet, Summary, Dependency, PackageSet};
+use util::CargoResult;
 
 pub trait Registry {
-    fn query<'a>(&'a self, name: &str) -> Vec<&'a Summary>;
+    fn query(&mut self, name: &Dependency) -> CargoResult<Vec<Summary>>;
 }
 
 impl Registry for Vec<Summary> {
-    fn query<'a>(&'a self, name: &str) -> Vec<&'a Summary> {
-        self.iter()
-          .filter(|summary| name == summary.get_name())
-          .collect()
+    fn query(&mut self, name: &Dependency) -> CargoResult<Vec<Summary>> {
+        Ok(self.iter()
+            .filter(|summary| name.get_name() == summary.get_name())
+            .map(|summary| summary.clone())
+            .collect())
+    }
+}
+
+pub struct PackageRegistry {
+    sources: Vec<Box<Source>>,
+    overrides: Vec<Summary>,
+    summaries: Vec<Summary>,
+    searched: Vec<SourceId>
+}
+
+impl PackageRegistry {
+    pub fn new(sources: Vec<Box<Source>>, overrides: SourceSet) -> CargoResult<PackageRegistry> {
+        Ok(PackageRegistry {
+            sources: sources,
+            overrides: try!(overrides.list()),
+            summaries: vec!(),
+            searched: vec!()
+        })
+    }
+
+    fn ensure_loaded(&mut self, namespace: &SourceId) -> CargoResult<()> {
+        if self.searched.contains(namespace) { return Ok(()); }
+        self.load(namespace);
+        Ok(())
+    }
+
+    fn load(&mut self, namespace: &SourceId) -> CargoResult<()> {
+        let source = namespace.load();
+
+        // Ensure the source has fetched all necessary remote data.
+        try!(source.update());
+
+        // Get the summaries
+        for summary in (try!(source.list())).iter() {
+            assert!(!self.summaries.contains(summary), "duplicate summaries");
+            self.summaries.push(summary.clone());
+        }
+
+        // Track that the source has been searched
+        self.searched.push(namespace.clone());
+
+        Ok(())
+    }
+}
+
+impl Registry for PackageRegistry {
+    fn query(&mut self, dep: &Dependency) -> CargoResult<Vec<Summary>> {
+        let overrides = try!(self.overrides.query(dep));
+
+        if overrides.is_empty() {
+            // Ensure the requested namespace is loaded
+            try!(self.ensure_loaded(dep.get_namespace()));
+            self.summaries.query(dep)
+        } else {
+            Ok(overrides)
+        }
     }
 }
index a67cbf1d19e9b3408a8ddc1e9e75a75859507a24..882c7399fa6749110754996cd2284b9dadebdc9c 100644 (file)
@@ -12,11 +12,11 @@ use util::result::CargoResult;
  * - The correct input here is not a registry. Resolves should be performable
  * on package summaries vs. the packages themselves.
  */
-pub fn resolve<R: Registry + Show>(deps: &[Dependency], registry: &R) -> CargoResult<Vec<PackageId>> {
+pub fn resolve<R: Registry + Show>(deps: &[Dependency], registry: &mut R) -> CargoResult<Vec<PackageId>> {
     log!(5, "resolve; deps={}; registry={}", deps, registry);
 
     let mut remaining = Vec::from_slice(deps);
-    let mut resolve = HashMap::<&str, &Summary>::new();
+    let mut resolve = HashMap::<String, Summary>::new();
 
     loop {
         let curr = match remaining.pop() {
@@ -28,14 +28,14 @@ pub fn resolve<R: Registry + Show>(deps: &[Dependency], registry: &R) -> CargoRe
             }
         };
 
-        let opts = registry.query(curr.get_name());
+        let opts = try!(registry.query(&curr));
 
         assert!(opts.len() > 0, "no matches for {}", curr.get_name());
         // Temporary, but we must have exactly one option to satisfy the dep
         assert!(opts.len() == 1, "invalid num of results {}", opts.len());
 
-        let pkg = opts.get(0);
-        resolve.insert(pkg.get_name(), *pkg);
+        let pkg = opts.get(0).clone();
+        resolve.insert(pkg.get_name().to_str(), pkg.clone());
 
         for dep in pkg.get_dependencies().iter() {
             if !resolve.contains_key_equiv(&dep.get_name()) {
@@ -47,12 +47,19 @@ pub fn resolve<R: Registry + Show>(deps: &[Dependency], registry: &R) -> CargoRe
 
 #[cfg(test)]
 mod test {
+    use url;
+
     use hamcrest::{
         assert_that,
         equal_to,
         contains
     };
 
+    use core::source::{
+        SourceId,
+        RegistryKind
+    };
+
     use core::{
         Dependency,
         PackageId,
@@ -66,7 +73,8 @@ mod test {
     macro_rules! pkg(
         ($name:expr => $($deps:expr),+) => (
             {
-            let d: Vec<Dependency> = vec!($($deps),+).iter().map(|s| Dependency::parse(*s, "1.0.0").unwrap()).collect();
+            let source_id = SourceId::new(RegistryKind, url::from_str("http://example.com").unwrap());
+            let d: Vec<Dependency> = vec!($($deps),+).iter().map(|s| Dependency::parse(*s, "1.0.0", &source_id).unwrap()).collect();
             Summary::new(&PackageId::new($name, "1.0.0", "http://www.example.com/"), d.as_slice())
             }
         );
@@ -81,7 +89,8 @@ mod test {
     }
 
     fn dep(name: &str) -> Dependency {
-        Dependency::parse(name, "1.0.0").unwrap()
+        let source_id = SourceId::new(RegistryKind, url::from_str("http://example.com").unwrap());
+        Dependency::parse(name, "1.0.0", &source_id).unwrap()
     }
 
     fn registry(pkgs: Vec<Summary>) -> Vec<Summary> {
@@ -96,47 +105,47 @@ mod test {
 
     #[test]
     pub fn test_resolving_empty_dependency_list() {
-        let res = resolve([], &registry(vec!())).unwrap();
+        let res = resolve([], &mut registry(vec!())).unwrap();
 
         assert_that(&res, equal_to(&names([])));
     }
 
     #[test]
     pub fn test_resolving_only_package() {
-        let reg = registry(vec!(pkg("foo")));
-        let res = resolve([dep("foo")], &reg);
+        let mut reg = registry(vec!(pkg("foo")));
+        let res = resolve([dep("foo")], &mut reg);
 
         assert_that(&res.unwrap(), equal_to(&names(["foo"])));
     }
 
     #[test]
     pub fn test_resolving_one_dep() {
-        let reg = registry(vec!(pkg("foo"), pkg("bar")));
-        let res = resolve([dep("foo")], &reg);
+        let mut reg = registry(vec!(pkg("foo"), pkg("bar")));
+        let res = resolve([dep("foo")], &mut reg);
 
         assert_that(&res.unwrap(), equal_to(&names(["foo"])));
     }
 
     #[test]
     pub fn test_resolving_multiple_deps() {
-        let reg = registry(vec!(pkg!("foo"), pkg!("bar"), pkg!("baz")));
-        let res = resolve([dep("foo"), dep("baz")], &reg).unwrap();
+        let mut reg = registry(vec!(pkg!("foo"), pkg!("bar"), pkg!("baz")));
+        let res = resolve([dep("foo"), dep("baz")], &mut reg).unwrap();
 
         assert_that(&res, contains(names(["foo", "baz"])).exactly());
     }
 
     #[test]
     pub fn test_resolving_transitive_deps() {
-        let reg = registry(vec!(pkg!("foo"), pkg!("bar" => "foo")));
-        let res = resolve([dep("bar")], &reg).unwrap();
+        let mut reg = registry(vec!(pkg!("foo"), pkg!("bar" => "foo")));
+        let res = resolve([dep("bar")], &mut reg).unwrap();
 
         assert_that(&res, contains(names(["foo", "bar"])));
     }
 
     #[test]
     pub fn test_resolving_common_transitive_deps() {
-        let reg = registry(vec!(pkg!("foo" => "bar"), pkg!("bar")));
-        let res = resolve([dep("foo"), dep("bar")], &reg).unwrap();
+        let mut reg = registry(vec!(pkg!("foo" => "bar"), pkg!("bar")));
+        let res = resolve([dep("foo"), dep("bar")], &mut reg).unwrap();
 
         assert_that(&res, contains(names(["foo", "bar"])));
     }
index 132f764e67ba47975a535896fa72fef0d3decaec..2188b316ae05d04bf7468b8f0fbe5e9c2875b4bf 100644 (file)
@@ -37,12 +37,17 @@ pub trait Source {
     fn get(&self, packages: &[PackageId]) -> CargoResult<Vec<Package>>;
 }
 
-#[deriving(Clone,PartialEq)]
+#[deriving(Show,Clone,PartialEq)]
 pub enum SourceKind {
-    GitKind(String)
+    /// GitKind(<git reference>) represents a git repository
+    GitKind(String),
+    /// represents a local path
+    PathKind,
+    /// represents the central registry
+    RegistryKind
 }
 
-#[deriving(Clone,PartialEq)]
+#[deriving(Show,Clone,PartialEq)]
 pub struct SourceId {
     pub kind: SourceKind,
     pub url: Url
@@ -52,6 +57,13 @@ impl SourceId {
     pub fn new(kind: SourceKind, url: Url) -> SourceId {
         SourceId { kind: kind, url: url }
     }
+
+    pub fn load(&self) -> Box<Source> {
+        match self.kind {
+            GitKind(ref reference) => unimplemented!(),
+            _ => unimplemented!()
+        }
+    }
 }
 
 pub struct SourceSet {
index 0b3dfede7c07a0df09e6f749a00ef49915b08baf..928e57f66023f69f0f6969561de2df4502f6b94f 100644 (file)
@@ -37,7 +37,6 @@ impl Summary {
 
 pub trait SummaryVec {
     fn names(&self) -> Vec<String>;
-    fn deps(&self) -> Vec<Dependency>;
 }
 
 impl SummaryVec for Vec<Summary> {
@@ -46,8 +45,4 @@ impl SummaryVec for Vec<Summary> {
         self.iter().map(|summary| summary.get_name().to_str()).collect()
     }
 
-    // TODO: Delete
-    fn deps(&self) -> Vec<Dependency> {
-        self.iter().map(|summary| Dependency::exact(summary.get_name(), summary.get_version())).collect()
-    }
 }
index 2353989c3d23c9cc42e1e02fbb083b938dbb80bd..67b4e7cbba7985d22d8434679f71d4871d3cda55 100644 (file)
@@ -26,6 +26,7 @@ use util::config::{ConfigValue};
 use core::{Package,PackageSet,Source,SourceSet};
 use core::resolver::resolve;
 use core::source::{GitKind,SourceId};
+use core::registry::PackageRegistry;
 use sources::{PathSource,GitSource};
 use sources::git::GitRemote;
 use ops;
@@ -38,27 +39,33 @@ pub fn compile(manifest_path: &Path) -> CargoResult<()> {
     let package = try!(PathSource::read_package(manifest_path));
     debug!("loaded package; package={}", package);
 
+    let overrides = try!(sources_from_config());
     let sources = try!(sources_for(&package));
 
-    try!(sources.update().wrap("unable to update sources"));
-    let summaries = try!(sources.list().wrap("unable to list packages from source"));
-    let resolved = try!(resolve(package.get_dependencies(), &summaries).wrap("unable to resolve dependencies"));
+    let registry = PackageRegistry::new(sources, overrides);
 
-    try!(sources.download(resolved.as_slice()).wrap("unable to download packages"));
+    //try!(sources.update().wrap("unable to update sources"));
+    //let summaries = try!(sources.list().wrap("unable to list packages from source"));
 
-    let packages = try!(sources.get(resolved.as_slice()).wrap("unable to get packages from source"));
+    //let registry = PackageRegistry::new(&summaries, &overrides);
 
-    log!(5, "fetch packages from source; packages={}; ids={}", packages, resolved);
+    //let resolved = try!(resolve(package.get_dependencies(), &summaries).wrap("unable to resolve dependencies"));
 
-    let package_set = PackageSet::new(packages.as_slice());
+    //try!(sources.download(resolved.as_slice()).wrap("unable to download packages"));
 
-    try!(ops::compile_packages(&package, &package_set));
+    //let packages = try!(sources.get(resolved.as_slice()).wrap("unable to get packages from source"));
+
+    //log!(5, "fetch packages from source; packages={}; ids={}", packages, resolved);
+
+    //let package_set = PackageSet::new(packages.as_slice());
+
+    //try!(ops::compile_packages(&package, &package_set));
 
     Ok(())
 }
 
-fn sources_for(package: &Package) -> CargoResult<SourceSet> {
-    let mut sources = try!(sources_from_config([package.get_manifest_path().dir_path()]));
+fn sources_for(package: &Package) -> CargoResult<Vec<Box<Source>>> {
+    let mut sources = vec!(box PathSource::new(vec!(package.get_manifest_path().dir_path())) as Box<Source>);
 
     let git_sources: Vec<Box<Source>> = try!(result::collect(package.get_sources().iter().map(|source_id: &SourceId| {
         match source_id.kind {
@@ -73,16 +80,17 @@ fn sources_for(package: &Package) -> CargoResult<SourceSet> {
                 let db_path = git.join("db").join(ident.as_slice());
                 let checkout_path = git.join("checkouts").join(ident.as_slice()).join(reference.as_slice());
                 Ok(box GitSource::new(remote, reference.clone(), db_path, checkout_path) as Box<Source>)
-            }
+            },
+            ref PathKind => fail!("Cannot occur")
         }
     })));
 
     sources.push_all_move(git_sources);
 
-    Ok(SourceSet::new(sources))
+    Ok(sources)
 }
 
-fn sources_from_config(additional: &[Path]) -> CargoResult<Vec<Box<Source>>> {
+fn sources_from_config() -> CargoResult<SourceSet> {
     let configs = try!(config::all_configs(os::getcwd()));
 
     debug!("loaded config; configs={}", configs);
@@ -94,9 +102,7 @@ fn sources_from_config(additional: &[Path]) -> CargoResult<Vec<Box<Source>>> {
         &config::List(ref list) => list.iter().map(|path| Path::new(path.as_slice())).collect()
     };
 
-    paths.push_all(additional);
-
-    Ok(vec!(box PathSource::new(paths) as Box<Source>))
+    Ok(SourceSet::new(vec!(box PathSource::new(paths) as Box<Source>)))
 }
 
 fn url_to_path_ident(url: &Url) -> String {
index 57f1f67b173135ad3d166fbd0fcea834ca04bc0c..a5fae1fb21ae058183d26ca8c615c727b390d6c5 100644 (file)
@@ -4,7 +4,7 @@ use url::Url;
 use std::collections::HashMap;
 use serialize::Decodable;
 
-use core::source::{SourceId,GitKind};
+use core::{SourceId,GitKind,RegistryKind};
 use core::manifest::{LibKind,Lib};
 use core::{Summary,Manifest,Target,Dependency,PackageId};
 use util::{CargoResult,Require,simple_human,toml_error};
@@ -130,20 +130,26 @@ impl TomlManifest {
         match self.dependencies {
             Some(ref dependencies) => {
                 for (n, v) in dependencies.iter() {
-                    let version = match *v {
-                        SimpleDep(ref string) => string.clone(),
+                    let (version, source_id) = match *v {
+                        SimpleDep(ref string) => {
+                            let source_id = SourceId::new(RegistryKind, url::from_str("http://example.com").unwrap());
+                            (string.clone(), source_id)
+                        },
                         DetailedDep(ref details) => {
-                            details.other.find_equiv(&"git").map(|git| {
+                            let source_id = details.other.find_equiv(&"git").map(|git| {
                                 // TODO: Don't unwrap here
                                 let kind = GitKind("master".to_str());
                                 let url = url::from_str(git.as_slice()).unwrap();
-                                sources.push(SourceId::new(kind, url));
+                                let source_id = SourceId::new(kind, url);
+                                sources.push(source_id.clone());
+                                source_id
                             });
-                            details.version.clone()
+
+                            (details.version.clone(), try!(source_id.require(simple_human("Dependencies must supply a git location"))))
                         }
                     };
 
-                    deps.push(try!(Dependency::parse(n.as_slice(), version.as_slice())))
+                    deps.push(try!(Dependency::parse(n.as_slice(), version.as_slice(), &source_id)))
                 }
             }
             None => ()