| use crate::compiler::BuildConfig; |
| use crate::compiler::RustcTargetData; |
| use crate::compiler::UserIntent; |
| use crate::compiler::standard_lib; |
| use crate::context::JobsConfig; |
| use crate::context::WarningHandling; |
| use crate::ops; |
| use crate::resolver::Resolve; |
| use crate::util::CargoResult; |
| use crate::util::GlobalContext; |
| use crate::util::data_structures::HashSet; |
| use crate::workspace::{PackageSet, Workspace}; |
| |
| pub struct FetchOptions<'a> { |
| pub gctx: &'a GlobalContext, |
| /// The target arch triple to fetch dependencies for |
| pub targets: Vec<String>, |
| } |
| |
| /// Executes `cargo fetch`. |
| pub fn fetch<'a>( |
| ws: &Workspace<'a>, |
| options: &FetchOptions<'a>, |
| ) -> CargoResult<(Resolve, PackageSet<'a>)> { |
| let parse_pass_output = crate::diagnostics::passes::emit_parse_diagnostics( |
| ws, |
| crate::diagnostics::rules::PARSE_PASS_RULES, |
| )?; |
| let dry_run = false; |
| let (mut packages, resolve) = ops::resolve_ws(ws, dry_run)?; |
| |
| let jobs = Some(JobsConfig::Integer(1)); |
| let keep_going = false; |
| let gctx = ws.gctx(); |
| let build_config = |
| BuildConfig::new(gctx, jobs, keep_going, &options.targets, UserIntent::Build)?; |
| let mut data = RustcTargetData::new(ws, &build_config.requested_kinds)?; |
| let mut fetched_packages = HashSet::default(); |
| let mut deps_to_fetch = ws.members().map(|p| p.package_id()).collect::<Vec<_>>(); |
| let mut to_download = Vec::new(); |
| |
| while let Some(id) = deps_to_fetch.pop() { |
| if !fetched_packages.insert(id) { |
| continue; |
| } |
| |
| to_download.push(id); |
| let deps = resolve |
| .deps(id) |
| .filter(|&(_id, deps)| { |
| deps.iter().any(|d| { |
| // If no target was specified then all dependencies are |
| // fetched. |
| if options.targets.is_empty() { |
| return true; |
| } |
| |
| // Otherwise we only download this dependency if any of the |
| // requested platforms would match this dependency. Note |
| // that this is a bit lossy because not all dependencies are |
| // always compiled for all platforms, but it should be |
| // "close enough" for now. |
| build_config |
| .requested_kinds |
| .iter() |
| .any(|kind| data.dep_platform_activated(d, *kind)) |
| }) |
| }) |
| .map(|(id, _deps)| id); |
| deps_to_fetch.extend(deps); |
| } |
| |
| // If -Zbuild-std was passed, download dependencies for the standard library. |
| if let Some(crates) = &gctx.cli_unstable().build_std { |
| let (std_package_set, _, _) = standard_lib::resolve_std( |
| ws, |
| &mut data, |
| &build_config, |
| crates, |
| &build_config.requested_kinds, |
| )?; |
| packages.add_set(std_package_set); |
| } |
| |
| packages.get_many(to_download)?; |
| crate::workspace::gc::auto_gc(gctx); |
| |
| if ws.gctx().warning_handling()? == WarningHandling::Deny |
| && parse_pass_output.lint_warning_count > 0 |
| { |
| anyhow::bail!("warnings are denied by `build.warnings` configuration") |
| } |
| |
| Ok((resolve, packages)) |
| } |