Stop downloading all packages immediately
authorAlex Crichton <alex@alexcrichton.com>
Mon, 22 Feb 2016 05:02:20 +0000 (21:02 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Fri, 26 Feb 2016 19:25:50 +0000 (11:25 -0800)
Instead delay all downloads until just before they're needed. This should ensure
that we don't download any more packages than we really need to.

src/cargo/core/package.rs
src/cargo/core/registry.rs
src/cargo/ops/cargo_compile.rs
src/cargo/ops/cargo_fetch.rs
tests/test_cargo_registry.rs

index b0c0c24617ae7b9f53a353fbc52ac71d962a1139..c3ec0dd61835a73dfc6b73aea16fca8b986a7329 100644 (file)
@@ -9,7 +9,7 @@ use semver::Version;
 use core::{Dependency, Manifest, PackageId, SourceId, Target};
 use core::{Summary, Metadata, SourceMap};
 use ops;
-use util::{CargoResult, Config, LazyCell, ChainError, internal};
+use util::{CargoResult, Config, LazyCell, ChainError, internal, human};
 use rustc_serialize::{Encoder,Encodable};
 
 /// Information about a package that is available somewhere in the file system.
@@ -125,11 +125,11 @@ pub struct PackageSet<'cfg> {
 }
 
 impl<'cfg> PackageSet<'cfg> {
-    pub fn new(packages: Vec<Package>,
+    pub fn new(package_ids: &[PackageId],
                sources: SourceMap<'cfg>) -> PackageSet<'cfg> {
         PackageSet {
-            packages: packages.into_iter().map(|pkg| {
-                (pkg.package_id().clone(), LazyCell::new(Some(pkg)))
+            packages: package_ids.iter().map(|id| {
+                (id.clone(), LazyCell::new(None))
             }).collect(),
             sources: RefCell::new(sources),
         }
@@ -151,7 +151,9 @@ impl<'cfg> PackageSet<'cfg> {
         let source = try!(sources.get_mut(id.source_id()).chain_error(|| {
             internal(format!("couldn't find source for `{}`", id))
         }));
-        let pkg = try!(source.download(id));
+        let pkg = try!(source.download(id).chain_error(|| {
+            human("unable to get packages from source")
+        }));
         assert!(slot.fill(pkg).is_ok());
         Ok(slot.borrow().unwrap())
     }
index bd44d77877793cf28a7b8261c713ce7332b1c6ac..f744f4937befba0f2c25ea41021cc36d33e9666d 100644 (file)
@@ -2,7 +2,7 @@ use std::collections::{HashSet, HashMap};
 
 use core::{Source, SourceId, SourceMap, Summary, Dependency, PackageId, Package};
 use core::PackageSet;
-use util::{CargoResult, ChainError, Config, human, internal, profile};
+use util::{CargoResult, ChainError, Config, human, profile};
 
 /// Source of information about a group of packages.
 ///
@@ -85,18 +85,9 @@ impl<'cfg> PackageRegistry<'cfg> {
         }
     }
 
-    pub fn get(mut self, package_ids: &[PackageId])
-               -> CargoResult<PackageSet<'cfg>> {
+    pub fn get(self, package_ids: &[PackageId]) -> PackageSet<'cfg> {
         trace!("getting packages; sources={}", self.sources.len());
-
-        let pkgs = try!(package_ids.iter().map(|id| {
-            let src = try!(self.sources.get_mut(id.source_id()).chain_error(|| {
-                internal(format!("failed to find a source listed for `{}`", id))
-            }));
-            src.download(id)
-        }).collect::<CargoResult<Vec<_>>>());
-
-        Ok(PackageSet::new(pkgs, self.sources))
+        PackageSet::new(package_ids, self.sources)
     }
 
     fn ensure_loaded(&mut self, namespace: &SourceId, kind: Kind) -> CargoResult<()> {
index 7d0f858eacf33c2bba097951769dc68d7182470d..d81f2b0a13183a112389989bab0e9e2ee97534a2 100644 (file)
@@ -133,8 +133,8 @@ pub fn resolve_dependencies<'a>(root_package: &Package,
             try!(ops::resolve_with_previous(&mut registry, root_package,
                                             method, Some(&resolve), None));
 
-    let packages = try!(ops::get_resolved_packages(&resolved_with_overrides,
-                                                   registry));
+    let packages = ops::get_resolved_packages(&resolved_with_overrides,
+                                              registry);
 
     Ok((packages, resolved_with_overrides))
 }
index 35002bac128904c14782260de28de27dcb86de4b..0617a68bfb01cc9d203101016cf8e6da4e96418c 100644 (file)
@@ -3,7 +3,7 @@ use std::path::Path;
 use core::registry::PackageRegistry;
 use core::{Package, PackageId, Resolve, PackageSet};
 use ops;
-use util::{CargoResult, Config, human, ChainError};
+use util::{CargoResult, Config};
 
 /// Executes `cargo fetch`.
 pub fn fetch<'a>(manifest_path: &Path,
@@ -12,16 +12,16 @@ pub fn fetch<'a>(manifest_path: &Path,
     let package = try!(Package::for_path(manifest_path, config));
     let mut registry = PackageRegistry::new(config);
     let resolve = try!(ops::resolve_pkg(&mut registry, &package));
-    get_resolved_packages(&resolve, registry).map(move |packages| {
-        (resolve, packages)
-    })
+    let packages = get_resolved_packages(&resolve, registry);
+    for id in resolve.iter() {
+        try!(packages.get(id));
+    }
+    Ok((resolve, packages))
 }
 
 pub fn get_resolved_packages<'a>(resolve: &Resolve,
                                  registry: PackageRegistry<'a>)
-                                 -> CargoResult<PackageSet<'a>> {
+                                 -> PackageSet<'a> {
     let ids: Vec<PackageId> = resolve.iter().cloned().collect();
-    registry.get(&ids).chain_error(|| {
-        human("unable to get packages from source")
-    })
+    registry.get(&ids)
 }
index 793235edeced091932fa371af2c6c902125a5a2a..bbc531978ad3444454866d06e9ccf2de31bc2de4 100644 (file)
@@ -567,6 +567,7 @@ test!(login_with_no_cargo_dir {
 });
 
 test!(bad_license_file {
+    Package::new("foo", "1.0.0").publish();
     let p = project("all")
         .file("Cargo.toml", r#"
             [project]
@@ -957,21 +958,52 @@ test!(update_same_prefix_oh_my_how_was_this_a_bug {
                 execs().with_status(0));
 });
 
-test!(use_semver {                                        
-    let p = project("foo")                                
-        .file("Cargo.toml", r#"                           
-            [project]                                     
-            name = "bar"                                  
-            version = "0.5.0"                             
-            authors = []                                  
+test!(use_semver {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [project]
+            name = "bar"
+            version = "0.5.0"
+            authors = []
 
-            [dependencies]                                
-            foo = "1.2.3-alpha.0"                         
-        "#)                                               
-        .file("src/main.rs", "fn main() {}");             
-    p.build();                                            
+            [dependencies]
+            foo = "1.2.3-alpha.0"
+        "#)
+        .file("src/main.rs", "fn main() {}");
+    p.build();
 
-    Package::new("foo", "1.2.3-alpha.0").publish();       
+    Package::new("foo", "1.2.3-alpha.0").publish();
 
     assert_that(p.cargo("build"), execs().with_status(0));
 });
+
+test!(only_download_relevant {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [project]
+            name = "bar"
+            version = "0.5.0"
+            authors = []
+
+            [target.foo.dependencies]
+            foo = "*"
+            [dev-dependencies]
+            bar = "*"
+            [dependencies]
+            baz = "*"
+        "#)
+        .file("src/main.rs", "fn main() {}");
+    p.build();
+
+    Package::new("foo", "0.1.0").publish();
+    Package::new("bar", "0.1.0").publish();
+    Package::new("baz", "0.1.0").publish();
+
+    assert_that(p.cargo("build"),
+                execs().with_status(0).with_stdout(&format!("\
+{updating} registry `[..]`
+{downloading} baz v0.1.0 ([..])
+{compiling} baz v0.1.0 ([..])
+{compiling} bar v0.5.0 ([..])
+", downloading = DOWNLOADING, compiling = COMPILING, updating = UPDATING)));
+});