Don't update the same path source multiple times

Updating a path source can be a possibly expensive operation (lots of
directories that need to be traversed), and currently the root path source is
updated three times:

* Once when the root package is initially loaded.
* Again when the first resolution pass happens over a graph.
* Finally a third when the second resolution pass happens over the graph.

This commit pushes through the original `Source` trait object into the
`PackageRegistry` and removes the implicit call to `add_sources`, pushing that
call up to the stack a bit.
This commit is contained in:
Alex Crichton 2015-05-19 22:50:26 -07:00
parent a1778efa74
commit ef8c651af1
7 changed files with 17 additions and 5 deletions

View file

@ -140,6 +140,11 @@ impl<'cfg> PackageRegistry<'cfg> {
Ok(())
}
pub fn preload(&mut self, id: &SourceId, source: Box<Source + 'cfg>) {
self.sources.insert(id, source);
self.source_ids.insert(id.clone(), (id.clone(), Kind::Locked));
}
pub fn add_sources(&mut self, ids: &[SourceId]) -> CargoResult<()> {
for id in ids.iter() {
try!(self.load(id, Kind::Locked));

View file

@ -98,10 +98,11 @@ pub fn compile<'a>(manifest_path: &Path,
for key in package.manifest().warnings().iter() {
try!(options.config.shell().warn(key))
}
compile_pkg(&package, options)
compile_pkg(&package, Some(Box::new(source)), options)
}
pub fn compile_pkg<'a>(package: &Package,
source: Option<Box<Source + 'a>>,
options: &CompileOptions<'a>)
-> CargoResult<ops::Compilation<'a>> {
let CompileOptions { config, jobs, target, spec, features,
@ -127,6 +128,12 @@ pub fn compile_pkg<'a>(package: &Package,
let (packages, resolve_with_overrides, sources) = {
let rustc_host = config.rustc_host().to_string();
let mut registry = PackageRegistry::new(config);
if let Some(source) = source {
registry.preload(package.package_id().source_id(), source);
} else {
try!(registry.add_sources(&[package.package_id().source_id()
.clone()]));
}
// First, resolve the package's *listed* dependencies, as well as
// downloading and updating all remotes and such.

View file

@ -14,6 +14,7 @@ pub fn fetch(manifest_path: &Path, config: &Config) -> CargoResult<()> {
let package = try!(source.root_package());
let mut registry = PackageRegistry::new(config);
registry.preload(package.package_id().source_id(), Box::new(source));
let resolve = try!(ops::resolve_pkg(&mut registry, &package));
let ids: Vec<PackageId> = resolve.iter().cloned().collect();

View file

@ -24,6 +24,7 @@ pub fn generate_lockfile(manifest_path: &Path, config: &Config)
try!(source.update());
let package = try!(source.root_package());
let mut registry = PackageRegistry::new(config);
registry.preload(package.package_id().source_id(), Box::new(source));
let resolve = try!(ops::resolve_with_previous(&mut registry, &package,
Method::Everything,
None, None));
@ -84,6 +85,7 @@ pub fn update_lockfile(manifest_path: &Path,
None => to_avoid.extend(previous_resolve.iter()),
}
registry.preload(package.package_id().source_id(), Box::new(source));
let resolve = try!(ops::resolve_with_previous(&mut registry,
&package,
Method::Everything,

View file

@ -178,7 +178,7 @@ fn run_verify(config: &Config, pkg: &Package, tar: &Path)
let new_pkg = Package::new(new_manifest, &manifest_path, &new_src);
// Now that we've rewritten all our path dependencies, compile it!
try!(ops::compile_pkg(&new_pkg, &ops::CompileOptions {
try!(ops::compile_pkg(&new_pkg, None, &ops::CompileOptions {
config: config,
jobs: None,
target: None,

View file

@ -36,8 +36,6 @@ pub fn resolve_with_previous<'a>(registry: &mut PackageRegistry,
previous: Option<&'a Resolve>,
to_avoid: Option<&HashSet<&'a PackageId>>)
-> CargoResult<Resolve> {
let root = package.package_id().source_id().clone();
try!(registry.add_sources(&[root]));
// Here we place an artificial limitation that all non-registry sources
// cannot be locked at more than one revision. This means that if a git

View file

@ -59,7 +59,6 @@ impl<'cfg> PathSource<'cfg> {
}
pub fn read_packages(&self) -> CargoResult<Vec<Package>> {
if self.updated {
Ok(self.packages.clone())
} else if self.id.is_path() && self.id.precise().is_some() {