|
1 |
| -use core::{PackageSet, Resolve, Workspace}; |
| 1 | +use core::compiler::{BuildConfig, Kind, TargetInfo}; |
| 2 | +use core::{Package, PackageId, PackageSet, Resolve, Workspace}; |
2 | 3 | use ops;
|
| 4 | +use std::collections::HashSet; |
3 | 5 | use util::CargoResult;
|
| 6 | +use util::Config; |
| 7 | + |
| 8 | +pub struct FetchOptions<'a> { |
| 9 | + pub config: &'a Config, |
| 10 | + /// The target arch triple to fetch dependencies for |
| 11 | + pub target: Option<String>, |
| 12 | +} |
4 | 13 |
|
5 | 14 | /// Executes `cargo fetch`.
|
6 |
| -pub fn fetch<'a>(ws: &Workspace<'a>) -> CargoResult<(Resolve, PackageSet<'a>)> { |
| 15 | +pub fn fetch<'a>( |
| 16 | + ws: &Workspace<'a>, |
| 17 | + options: &FetchOptions<'a>, |
| 18 | +) -> CargoResult<(Resolve, PackageSet<'a>)> { |
7 | 19 | let (packages, resolve) = ops::resolve_ws(ws)?;
|
8 |
| - for id in resolve.iter() { |
9 |
| - packages.get(id)?; |
10 |
| - } |
| 20 | + |
| 21 | + fetch_for_target(ws, options.config, &options.target, &resolve, &packages)?; |
| 22 | + |
11 | 23 | Ok((resolve, packages))
|
12 | 24 | }
|
| 25 | + |
| 26 | +fn fetch_for_target<'a, 'cfg: 'a>( |
| 27 | + ws: &'a Workspace<'cfg>, |
| 28 | + config: &'cfg Config, |
| 29 | + target: &Option<String>, |
| 30 | + resolve: &'a Resolve, |
| 31 | + packages: &'a PackageSet<'cfg>, |
| 32 | +) -> CargoResult<HashSet<&'a PackageId>> { |
| 33 | + let mut fetched_packages = HashSet::new(); |
| 34 | + let mut deps_to_fetch = Vec::new(); |
| 35 | + let jobs = Some(1); |
| 36 | + let build_config = BuildConfig::new(config, jobs, target, None)?; |
| 37 | + let target_info = TargetInfo::new(config, &build_config, Kind::Target)?; |
| 38 | + let root_package_ids = ws.members().map(Package::package_id).collect::<Vec<_>>(); |
| 39 | + |
| 40 | + deps_to_fetch.extend(root_package_ids); |
| 41 | + |
| 42 | + while let Some(id) = deps_to_fetch.pop() { |
| 43 | + if !fetched_packages.insert(id) { |
| 44 | + continue; |
| 45 | + } |
| 46 | + |
| 47 | + let package = packages.get(id)?; |
| 48 | + let deps = resolve.deps(id); |
| 49 | + let dependency_ids = deps.filter(|dep| { |
| 50 | + package |
| 51 | + .dependencies() |
| 52 | + .iter() |
| 53 | + .filter(|d| d.name() == dep.name() && d.version_req().matches(dep.version())) |
| 54 | + .any(|d| { |
| 55 | + // If no target was specified then all dependencies can be fetched. |
| 56 | + let target = match *target { |
| 57 | + Some(ref t) => t, |
| 58 | + None => return true, |
| 59 | + }; |
| 60 | + // If this dependency is only available for certain platforms, |
| 61 | + // make sure we're only fetching it for that platform. |
| 62 | + let platform = match d.platform() { |
| 63 | + Some(p) => p, |
| 64 | + None => return true, |
| 65 | + }; |
| 66 | + platform.matches(target, target_info.cfg()) |
| 67 | + }) |
| 68 | + }).collect::<Vec<_>>(); |
| 69 | + |
| 70 | + deps_to_fetch.extend(dependency_ids); |
| 71 | + } |
| 72 | + |
| 73 | + Ok(fetched_packages) |
| 74 | +} |
0 commit comments